- •Глава 3 управление ходом выполнения программы
- •3. 1. Как выполняется запрос в прологе
- •Три семантические модели
- •Выполнение запроса
- •Правила, описывающие унификацию термов
- •Пример с программой "дядя"
- •Активация запроса
- •Унификация запроса
- •Обработка тела фразы
- •Обработка подцели "брат"
- •Обработка подцели "отец"
- •Неудача запроса и возврат назад
- •Поиск третьего ответа
- •Поиск несуществующих ответов
- •Выполнение запроса к правилу "регистрация"
- •Автоматический просмотр выполнения программы
- •3.2. Предикат "сократить" Пространство поиска запроса
- •Предикат "сократить" останавливает возврат назад
- •Влияние предиката "сократить" на составной запрос
- •Влияние предиката "сократить" на процедуру
- •Предикат "сократить" как подцель в составном запросе
- •Использование предиката "сократить" для того, чтобы сделать процедуру детерминированной
- •Применение предиката "сократить" для отбрасывания части пространства поиска
- •Ограничение сферы действия предиката "сократить"
- •Общее правило ограничения сферы действия предиката "сократить"
- •3. 3. Отрицание как неудача запроса Негативная информация
- •Предположение о замкнутости мира
- •Тогда и только тогда, когда
- •Предположение об открытости мира
- •Отрицание в явной форме
- •Пример процедуры, поведение которой соответствует предположению об открытости мира
- •3. 4. Встроенные предикаты, предназначенные для обеспечения ввода-вывода Побочные эффекты ввода-вывода
- •Пример запроса, в котором используется предикат "read"
- •3. 5. Встроенные предикаты, предназначенные для управления файлами
- •3. 6. Проверка типа терма
- •Использование предикатов "var" и "nonvar"
- •3. 7. Действия с текущей программой
- •Изменение значения факта
- •Алгоритм поиска с возрастом, в котором используется предикат "assert"
- •Процедура, которая учится у пользователя
- •Программа, которая модифицирует сама себя
- •3. 8. Компараторы
- •3. 9. Прочие встроенные предикаты
- •Программа ввода "вводполя"
- •3. 10. Операции Расширяемость синтаксиса языка Пролог
- •Инфиксная операция ",", обладающая правой ассоциативностью
- •Инфиксная операция, не обладающая свойством ассоциативности
- •Объявление операций
- •3. 11. Преобразование процедурного алгоритма в программу на языке пролог Сравнение поиска с возвратом и рекурсии
- •Цикл "пока"
- •Рекурсия
- •Поиск с возвратом
- •Применение предиката "findall"
- •Библиографические заметки
- •Упражнения
Обработка подцели "отец"
Интерпретатор пытается унифицировать подцель «отец (билл, W)» с фразой «отец (билл, даниэль)». Эта попытка приводит к успеху, в результате чего конкретизируется переменная W. Она получает значение «даниэль». Теперь состояние интерпретатора таково:
(8)
- Активные запросы - - Фразы программы -
? -дядя (джон, даниэль). ------> дядя (джон, даниэль): -
брат (джон, билл),
отец (билл, даниэль).
брат (даниэль, кеннет).
? -брат (джон, билл). ------> брат (джон, билл).
? -отец (билл, даниэль). ------> отец (билл, даниэль).
отец (билл, кеннет).
Фраза «отец (билл, даниэль)» является фактом, поэтому запрос "отец" сразу же оказывается успешным. Больше подцелей в теле правила "дядя" нет, следовательно, и исходный запрос "дядя" будет успешным. Интерпретатор выводит значение переменной W:
W = даниэль
Обратите внимание на то, что после отыскания первого ответа весь стек активных запросов сохраняется.
Неудача запроса и возврат назад
Если активный запрос достигнет конца соответствующего множества фраз, то он завершится неудачей. Если такой активный запрос служит частью составного запроса (т. е. списка подцелей) и не является первой подцелью этого составного запроса, то интерпретатор возвратится назад, чтобы повторно проанализировать предыдущую подцель составного запроса. Если же активный запрос является первой подцелью составного запроса, то неудача активного запроса приводит к неудаче всего составного запроса. Когда интерпретатор возвращается назад, ликвидируются все конкретизации переменных, выполненные последним активным запросом.
Указание интерпретатору вернуться назад - ввод символа;
После того как интерпретатор найдет один ответ на запрос, пользователь может попросить найти еще один ответ. Для этого вводится символ;, который означает отказ от только что полученного ответа. Это заставляет интерпретатор возвратиться назад и приступить к поиску другого ответа. Точнее говоря, ввод символа ; приводит к неудаче запроса, активированного самым последним (т. е. запроса, расположенного в вершине стека). Это происходит уже после получения позитивного ответа на запрос. Интерпретатор покидает текущее положение в множестве соответствующих фраз. Если переменные были конкретизированы при последнем успешном выполнении данного запроса, то результаты конкретизации теряют свою силу. Интерпретатор приступает к повторной обработке этого запроса, начиная со следующей доступной фразы.
Другой ответ на запрос "дядя "
Предположим, что после получения первого ответа "W = даниэль" на запрос "дядя" пользователь вводит символ ; . Подцель "отец", стоящая в вершине стека, принудительно делается неудачной, а конкретизация переменной W, осуществленная при последнем успехе этой цели, теряет свою силу. Интерпретатор переходит к попытке унифицировать данную подцель со следующей доступной фразой "отец":
(9)
— Активные запросы — - Фразы программы -
? -дядя (джон, W), ------> дядя (джон, W): -
брат (джон, билл),
отец (билл, W).
брат (данизль, кеннет).
? - брат (джон, билл). ------> брат (джон, билл).
отец (билл, даниэль).
? -отец (билл, W), ------> отец (билл, кеннет).
Интерпретатор унифицирует подцель «отец (билл, W)» с фразой «отец (билл, кеннет)». В результате этого выполняется конкретизация переменной W, которая получает значение «кеннет». Теперь состояние интерпретатора таково:
(10)
— Активные запросы - — Фразы программы —
? - дядя (джон, кеннет). ------> дядя (джон. кеннет): -
брат (джон, билл),
отец (билл, кеннет).
брат (даниэль, кеннет).
? - брат (джон, билл). ------> брат (джон, билл).
отец (билл, даниэль).
? -отец (билл, кеннет). ------ > отец (билл, кеннет).
Здесь запрос "дядя" опять оказывается успешным. Интерпретатор выведет новое значение переменной W:
W= кеннет