Ограничение сферы действия предиката "сократить"

Необходимо найти способ ограничить сферу действия предиката "сократить ". Мы хотим сохранить влияние этого предиката на подцель "возраст", устранив одновременно действие данного предиката на составной запрос, образующий тело правила "регистрация". Этого можно добиться, если перенести предикат "сократить" из правила "регистрация" на более низкий уровень, каким и является сама база данных "возраст". Построим базу данных "хвозраст", в которой каждая фраза является правилом с единственной подцелью - предикатом "сократить".

хвозраст (брайен, 18): -!.

хвозраст (майк, 17): -!.

хвозраст (стив, 18): -!.

регистрацияЗ (X): -

мужчина (X), хвозраст (X, Y), Y==l8.

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

|? - регистрацияЗ (майк).

нет

|? - регистрацияЗ (X).

Х= брайен ;

Х=стив ;

нет

Поскольку в каждое правило "хвозраст" входит предикат "сократить", интерпретатор не будет пытаться найти у кого-нибудь более чем один возраст. Тем самым отбрасывается бесполезная часть пространства поиска, что не оказывает никакого влияния на полноту множества ответов. В соответствии с приведенным выше запросом были найдены и Брайен, и Стив.

Однако решив проблему для правила "регистрация", мы создали новые трудности для правил "хвозраст". Простой запрос к "хвозраст" с аргументами-переменными не позволяет получить из базы данных все сведения об именах и возрасте людей:

|? -хвозраст (X, Y).

Х = брайен

Y-18;

нет

Совершенно очевидно, что множество ответов является неполным. В базе данных есть и другие ответы, но интерпретатор не найдет их из-за действия предиката "сократить". Такой способ использования предикатов "сократить" приводит к ухудшению модульности программы - в том смысле, что на любое правило или составной запрос, в которых предпринимается попытка применения правил "хвозраст" в качестве подцели, будут также влиять и предикаты "сократить", расположенные в теле правил "хвозраст". В идеале программист не должен был бы думать о том, как предикат "сократить", расположенный в подпроцедуре, будет влиять на вызывающую ее процедуру.

Общее правило ограничения сферы действия предиката "сократить"

При более гибком подходе к этой проблеме следует оставить базу данных "возраст" в ее исходном виде, т. е. без предикатов "сократить", и написать специальное правило, задача которого заключается только лишь в ограничении сферы действия предиката "сократить". Аргументом такого правила, названного "один_раз", является запрос. Тело этого правила состоит из двух подцелей — из запроса и предиката "сократить". При выполнении правила "один_раз" этот предикат гарантирует, что будет найден только один ответ на запрос. Если правило "один_раз" войдет в составной запрос, то интерпретатор сможет возвратиться назад через него, т. е. это правило не оказывает на составной запрос такого действия, как предикат "сократить". Приведем определение правила "один_раз" и версию процедуры "регистрация", в которой это правило используется:

один_раз (Р): -

Р,!.

регистрация4 (X): -

мужчина (X), один_раз (возраст (X, Y)), Y==18.

|? -регистрация4 (брайен).

да

|? - регистрация4 (X).

X = бранен ;

Х=стив;

нет

Если Вам непонятно такое использование правила "один_раз", то вспомните, что аргументом предиката может быть структура. В запросе к правилу "один_раз" структурой является «возраст (Х, Y)». Эта структура преобразуется внутри правила "один_раз" в подцель.

Программа "регистрация4" удовлетворяет нашим требованиям во всех отношениях. Поскольку в правило "один_раз" включен предикат "сократить", интерпретатор не будет понапрасну тратить время на поиски еще одного возраста для одного и того же человека. База данных "возраст" не содержит предикатов "сократить", и поэтому ее можно использовать не только в программе "регистрация4", но и для других целей (т. е. сохраняется модульность). В тело правила "регистрация4" предикат "сократить" напрямую не входит, поэтому множество ответов на запрос к программе "регистрация4" будет полным.

Соседние файлы в папке Гл.0,1,2,3,4,5,Предисловие