- •Приложение 4-5
- •IV. Версии языка пролог СиПролог Поставщик
- •Синтаксис и встроенные предикаты
- •Директивы
- •Среда для разработки программ
- •Отладчик
- •Отладочные команды
- •Компилятор
- •Запомненные состояния
- •Интерфейс с иными языками программирования
- •Расширения языка
- •Квинтус Пролог Поставщик
- •Синтаксис и встроенные предикаты
- •Директивы
- •Среда разработки программ
- •Отладчик
- •Компилятор
- •Запомненные состояния
- •Система программирования на Прологе фирмы Сайлоджик Поставщик
- •Синтаксис и встроенные предикаты
- •Директивы
- •Среда разработки программ
- •Отладчик
- •Компилятор
- •Запомненные состояния
- •Интерфейс с иными языками программирования
- •Расширения
- •Пролог-2 Поставщик
- •Синтаксис и встроенные предикаты
- •Директивы
- •Среда разработки программ
- •Отладчик
- •Компилятор
- •Запомненные состояния
- •Интерфейс с иными языками программирования
- •Расширения
- •Эрити Пролог Поставщик
- •Синтаксис и встроенные предикаты
- •Среда разработки программ
- •Отладчик
- •Компилятор
- •Запомненные состояния
- •Расширения
- •Унсв Пролог Поставщик
- •Синтаксис и встроенные предикаты
- •Директивы
- •Среда разработки программ
- •Отладчик
- •Компилятор
- •Запомненные состояния
- •Интерфейс с иными языками программирования
- •Турбо Пролог Поставщик
- •Синтаксис и встроенные предикаты
- •Среда разработки программ
- •Отладчик
- •Запомненные состояния
- •Интерфейс с иными языками программирования
- •Расширения
- •V. Ответы к упражнениям Ответы к упражнениям
- •Глава 2
- •Глава 3
- •Глава 5
- •Глава 6
- •Глава 7
Глава 6
1. Отношение "является" можно гарантировано превратить в транзитивное, если задать явную базу данных "является0" и написать рекурсивную процедуру "является", которая обращается к базе данных "является0":
является0 (канарейка, птица).
является0(твити, канарейка).
является (X, Y);—
является0 (X, Y).
является (X, Y) :—
является0 (X, Z),
является (Z,Y).
Однако отношения "летает" и "цвет" сами являются транзитивными (рекурсивными), причем это их свойство зависит от отношения "является". Для того чтобы предотвратить бесконечную рекурсию при обработке запросов к этим процедурам, нужно заменить подцель "является" в теле каждого рекурсивного правила на подцель "является0":
летает (птица).
летает (X) :- является0 (X,Y), летает (Y).
цвет (канарейка, желтый).
цвет(Х, Y):- является0(Х, Z), цвет(Z, Y).
2.
является0 (квадрат, прямоугольник).
является0 (прямоугольник. параллелограмм).
свойство (параллелограмм,
'площадь равна произведению основания на высоту').
свойство (прямоугольник,
'все углы равны 90 градусам').
свойство (квадрат, 'все стороны равны').
свойство (Узел, Свойство) :—
является0 (Узел, ДругойУзел),
свойство (ДругойУзел, Свойство).
3.
подсчет (Состояние, Счетчик) :—
% ввести критерий выбора:
послать (Состояние, за (тип, Т)),
послать (Состояние, за (марка, М) ),
послать(Состояние,за(вес,B)),
послать(Состояние,за(поверхность,П)),
послать (Состояние, за (цвет, Ц)),
!,
% подсчитать количество целостных информационных
% элементов, удовлетворяющих критериям выбора:
findall (Т, вед_бум (бумага. Т, М, В, П, Ц), Список),
длина (Список, Счетчик).
Примечание: при обращении к встроенному предикату "findall" не имеет никакого значения, какие сведения фактически собираются в список "Список", так как нас интересует лишь количество элементов списка, а не его содержание.
Глава 7
1. Пример базы данных с циклическими данными:
путешествие (амтрак, нью_йорк, бостон, поезд).
путешествие (грейхаунд, бостон, нью_йорк, автобус).
Обычный интерпретатор, выполняя нижеследующий запрос к процедуре "'можно путешествовать4":
| ?— можно путешествовать4 (нью йорк, X).
будет вырабатывать ответы по такой схеме:
Х = бостон ;
Х = нью йорк ;
Х= бостон ;
Х = нью_йорк ;
Еслли данный запрос выполнять при помощи процедуры "иоц", то будут получены точно такие же ответы. Процедура "иоц" обнаруживает только те циклы, в которых одна и та же подцель попадается три раза подряд. Приведенный выше запрос входит в осциллирующий цикл, который интерпретатор "иоц" не сможет обнаружить. Наилучшее решение проблемы осцилляции было предложено в процедуре "тснр_путешествовать3" из гл. 4. Можете ли Вы написать универсальную программу-решатель задач, которая будет обнаруживать осциллирующие множества ответов, используя ту же методику, какая была применена в процедуре "тснр-путешествоватьЗ"?
2. Ввиду того что успешный вызов процедуры "поместить" фактически приводит к переходу из одного состояния в другое, смысл данного вызова станет более ясным, если имена нужных состояний будут фигурировать в качестве аргументов этой процедуры, например:
% + + ?
поместить (Объект, Куда_поместить, ТекущСост, НовСост) :—
…
3.
% объявить свойство один-к-многим отношения "мать"
% Отношение Один Много
один_много (мать (Мать, Ребенок), Мать, Ребенок).
% объявить свойство один-к-одному отношения
% "соц_страх_номер":
% Отношение Один Один
один_один (соц_страх_номер (Имя, Номер), Имя, Номер).
% решатель задач, которому известно про отношения
% один-к-одному и один-к-многим:
рз(truе):— !.
рз((А, Б)) :— % составной запрос
!,
рз(А),
рз(б).
рз(А) :— % особый случай: А - это отношение вида
% один-к-многим
один много (А, X, Y),
!,
ом_рз(А,Х,У).
рз(А) :- % особый случай : А - это отношение вида
% один-к-одному один_один(А, X, Y),
оо_рз(А,Х,У).
рз(А) :— % отношение А не является ни отношением
% вида один-к-одному, ни отношением вида
% один-к-многим
clause (А, Тело),
рз(Тело).
% эффективно обработать отношение вида один-к-многим:
% Один Много
ом_рз(А, X, Y) :-
nonvar(Y),
clause (А, Тело),
рз(Тело),!.
ом_ pз(A,X,Y):-
var(Y),
clause (А, Тело),
рз(Тело).
% эффективно вычислить отношение вида один-к-одному:
% Один Один
оо_рз(А, X, Y):-
clause(A, Тело),
рз(Тело),!.
Отношения вида многие-к-одному можно реализовать, объявив их как отношения вида "один_много" и изменив порядок следования аргументов на обратный.