- •Глава 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"
- •Библиографические заметки
- •Упражнения
Алгоритм поиска с возрастом, в котором используется предикат "assert"
Напишем еще один составной запрос, при помощи которого пользователь опрашивается о знании языков. Данный запрос добавляет факты со сведениями о пользователе в базу данных.
язык (итальянский).
язык (немецкий).
язык (японский).
язык (французский).
язык (английский).
|? — write ('Введите Ваше имя: '),
read (Имя),
язык (Яз),
write ('Знаете ли Вы'), write (Яз),
write ('язык'), n1,
read (да),
assert (владеет (Имя. Яз)),
fail.
Введите Ваше имя: брайен.
Знаете ли Вы итальянский язык?
нет.
Знаете ли Вы немецкий язык?
нет.
Знаете ли Вы японский язык?
да.
Знаете ли Вы французский язык?
нет.
Знаете ли Вы английский язык?
да.
нет
|? - владеет (брайен, Y).
Y= японский;
Y= английский;
нет
Сначала данный составной запрос спрашивает имя пользователя. Две подцели, применяющиеся в предыдущей Версии программы, - «read (А)» и «А = да» — теперь объединены в одну - «read (да)», которая будет истинной только в том случае, когда пользователь введет слово «да». Если пользователь признается, что знает определенный язык, то в базу данных добавляется факт вида «владеет (Имя, Яз)». Встроенный предикат "fail" всегда приводит к неудаче. Подцель "fail" заставляет интерпретатор возвратиться назад и взять для рассмотрения новый язык. Этот процесс будет продолжаться до тех пор, пока не исчерпается перечень языков, после чего весь составной запрос потерпит неудачу.
В конце описанного выше сеанса работы вводится запрос к базе данных "владеет", позволяющий отобразить фразы, добавленные в результате выполнения составного запроса. Несмотря на то, что в конце концов составной запрос потерпел неудачу, он оказал перманентное воздействие на текущую программу, осуществив добавление в нее двух фраз "владеет".
Как превратить составной запрос в правило?
Процедура, которая учится у пользователя
Предикат "место" связывает название места в городе с номерами улиц (стрит и авеню), на пересечении которых это место расположено. По заданному названию места данная процедура попытается определить его адрес, просматривая базу данных "адрес". Процедура "место" действует в соответствии с предположением об открытости мира в том смысле, что она не просто завершается неудачей, если не может найти название места в базе данных "адрес". Вместо этого процедура переключается на другую стратегию и получает сведения от пользователя, выступающего в роли альтернативного источника знаний. Процедура "место" учится на своем опыте, добавляя новые ответы в текущую программу.
адрес (уайтхорс, 8, 11).
адрес (урбан_софтвэр, 8, 42).
адрес (милфорд_плаза, 8, 43).
адрес (пенн_стейшн, 7,32).
место (X, Авеню, Стрит): -
адрес (X, Авеню, Стрит),!.
место (X, Авеню, Стрит): -
nonvar (X), var (Авеню), var (Стрит),
write ('- - Это место — '), write (X), n1,
write (' вблизи какой авеню? (название+ точка)'),
read (Авеню),
write ('вблизи какой стрит? (номер+ точка) '),
read (Стрит),
assert (адрес (X, Авеню, Стрит)).
Нижеследующие запросы иллюстрируют работу процедуры "место":
|? - место (уайтхорс, Аве, Ст).
Аве=8
Cт=11
|? -место (гранд_сентрал, Аве, Ст).
--Это место-гранд_сентрал
вблизи какой авеню? (название+ точка) лексингтон.
вблизи какой стрит? (номер+ точка) 42.
Аве =лексингтон
Ст=42
|?— место (гранд_сентрал, Аве, Ст).
Аве=лексингтон
Ст=42
Заметьте, что при выполнении второго запроса система спросила у пользователя адрес «гранд_сентрал». Пользователь ввел «лексингтон» и «42», а затем интерпретатор вывел эти же самые значения как ответы на запрос. Если дать тот же запрос повторно, то процедура "место" уже будет знать адрес «гранд_сентрал».
Ограничение, обеспечивающее целостность предиката "место"
Какое ограничение, обеспечивающее целостность, будет справедливо для отношения названия места и его адреса — один-к-одному, один-к-многим или многие-к-многим? Какое ограничение, обеспечивающее целостность, действует неявно для приведенной выше версии правила "место"?
Можете ли Вы составить новую версию процедуры "место", которая выполняла бы некоторые рациональные действия при таком запросе:
|? -место (Что, 8, 21).
если в базе данных "адрес" нет сведений о каком-либо объекте, располагающемся на пересечении 8-й Авеню и 21-й Стрит?