'гоpод(Шифр, Город)',
|
'аннотация(Шифр, Аннотация)']). |
book(X):- |
|
% |
functor(X, книга, 10), call(X). |
Утилиты для пользователя: |
|
автоp(Sh, Av) :- book(X), arg(1, X, Sh), arg(2, X, Av). название(Sh, Naz) :- book(X), arg(1, X, Sh), arg(3, X, Naz). томов(Sh, TT) :- book(X), arg(1, X, Sh), arg(4, X, TT). том(Sh, T) :- book(X), arg(1, X, Sh), arg(5, X, T). стpаниц(Sh, Str) :- book(X), arg(1, X, Sh), arg(6, X, Str). год(Sh, God) :- book(X), arg(1, X, Sh), arg(7, X, God). издательство(Sh, Izd) :- book(X), arg(1, X, Sh), arg(8, X, Izd). гоpод(Sh, Gor) :- book(X), arg(1, X, Sh), arg(9, X, Gor). аннотация(Sh, Ann) :- book(X), arg(1, X, Sh), arg(10, X, Ann).
С использованием утилит перечисленные выше примеры запросов пользователя к библиотечной базе данных легко записать в виде следующих целей Пролога:
?- город(S, 'Рига'), автор(S, X).
?- томов(S, 2), название(S, N), автор(S, A), издательство(S, I).
?- автор(S, 'Пушкин А.С.'), год(S, G), G < 1990,
название(S, N).
?- город(S, G), G =\= 'Москва', издательство(S, I).
5. Интерпретация операций реляционной алгебры
Рассмотрим возможности реализации операций реляционной алгебры средствами Пролога.
Как известно, основными операциями реляционной алгебры яв-
ляются: проекция, соединение, пересечение и объединение отноше-
ний. Ограничимся операцией проекции - выделением части атрибутов отношения с исключением появляющихся при этом повторений.
116
Пример 8.4. Рассмотрим уже имеющееся отношение книга/10. Проекцией этого отношения на атрибуты город и издательство
будет новое отношение, которое мы назовем место/2. После исключения повторений в этом отношении будет 5 строк. Его будут представлять следующие факты Пролога:
место('Москва', 'Художественная литеpатуpа'). место('Москва', 'Русский язык').
место('Рига', 'Лиесма').
место('Москва', 'Московский pабочий'). место('Москва', 'Пpавда').
Рассмотрим определение предиката proj/2. Первым аргументом предиката служит спецификация исходного отношения в виде R/N, вторым аргументом – структура проекции в виде P/L, где P – имя нового отношения, а L – список номеров атрибутов исходного отношения, на которые оно проецируется.
Запрос на получение рассмотренной выше проекции следующий:
?- proj(книга/10, место/[9, 8]).
Определение предиката proj/2 таково (код 8.6):
Код 8.6
proj(R/N, P/L):-
functor(S, R, N), proj1(S, P/L).
proj1(S, P/L):- call(S), otobr(S, L, M),
Result =.. [P|M], assert_new_fact(Result), fail.
proj1(_, _):-!.
otobr(_, [], []):-!. otobr(S, [I|L], [X|M]):-
arg(I, S, X), otobr(S, L, M).
assert_new_fact(Fact):- call(Fact), !.
117
assert_new_fact(Fact):- assert(Fact), !.
Напомним, что использование предиката assert_new_fact/1 вместо встроенного предиката assert/1 обеспечивает устранение повторяющихся строк в результирующем отношении (одинаковых фактов Пролога).
В заключение сделаем следующее замечание. Интерпретация отношений реляционных баз данных в виде фактов Пролога, находящихся в оперативной памяти компьютера, позволяет работать,
естественно, лишь с небольшими, «игрушечными» базами. В некоторых реализациях Пролога (например, в системе Atity Prolog, опи-
санной в книге [3]) предусмотрены возможности взаимодействия Пролога с внешними носителями – с файлами, с виртуальной памятью, что позволяет говорить уже не об «игрушечных» примерах, а о реальных дедуктивных базах данных.
6.О статических и динамических предикатах Пролог системы LPA
ВПрологе LPA есть специфика – определяемые предикаты подразделяются на статические и динамические.
По умолчанию, при компиляции новых определений предикатов
спомощью встроенных предикатов consult/1 (перезагрузки) и compile/1 (компиляции) загружаемые и компилируемые предикаты считаются статическими.
С помощью встроенных предикатов assert/1 и retract/1 можно добавлять и удалять определения только динамических предикатов.
Определения статических предикатов могут быть изменены
лишь полным переопределением с помощью встроенных предика-
тов consult/1 и compile/1.
Полное удаление определений как статических, так и динамиче-
ских предикатов может быть произведено с помощью встроенного предиката abolish/1.
Определения статических предикатов можно удалить и другим
способом, объявив эти предикаты динамическими с помощью встроенного предиката dynamic/1.
Взаключение рассмотрим пример на использование динамических и статических предикатов.
118
Пример 8.5. Рассмотрим запись правил и фактов в БД Пролога. Задача такая: с помощью предиката task1 в базу данных запи-
сывается новое правило c( X, Y) :- a( X), b( Y)., позволяющее искать значения переменных X и Y по запросу: ?- c(X, Y).
Код 8.7
% Запись факта и правила в БД Пролога
:- dynamic( b/1).
a( Петя). a( Вася). b( Маша).
task1 :- assert( (c( X, Y) :- (a( X), b( Y)))). task2 :- assert( b( Даша)).
%Если несколько раз отрабатывать цель ?- task2.
%то в БД появятся несколько фактов b( Даша).
%Избежать этого можно, заменив assert/1 на assert_new_fact/1:
assert_new_fact( F) :- call( F), !. assert_new_fact( F) :- !, assert( F).
Комментарий. Для снятия блокировки при попытке записать новый факт b(Даша) в базу данных Пролога, когда в ней уже есть факт b(Маша), используется директива :- dynamic( b/1).
Следующая «фотография» консоли (код 8.8) достаточно красно-
речиво описывает результаты экспериментов с данной программой.
Код 8.8
| ?- task1. yes
| ?- bagof((X,Y), c(X,Y), L). X = _ ,
Y = _ ,
L = [(Петя,Маша),(Вася,Маша)]
| ?- task2. yes
| ?- bagof((X,Y), c(X,Y), L).
119
X = _ ,
Y = _ ,
L = [(Петя,Маша),(Петя,Даша),(Вася,Маша),(Вася,Даша)]
| ?- assert_new_fact(b(Глаша)). yes
| ?- bagof((X,Y), c(X,Y), L). X = _ ,
Y = _ ,
L = [(Петя,Маша),(Петя,Даша),(Петя,Глаша),(Вася,Маша), (Вася,Даша), (Вася,Глаша)]
| ?- assert_new_fact(b(Даша)). yes
| ?- bagof((X,Y), c(X,Y), L). X = _ ,
Y = _ ,
L = [(Петя,Маша),(Петя,Даша),(Петя,Глаша),(Вася,Маша), (Вася,Даша),(Вася,Глаша)]
| ?- task2. yes
| ?- bagof((X,Y), c(X,Y), L). X = _ ,
Y = _ ,
L = [(Петя,Маша),(Петя,Даша),(Петя,Глаша),(Петя,Даша),
(Вася,Маша),(Вася,Даша),(Вася,Глаша),(Вася,Даша)]
| ?-
Отметим, что попытка записать в базу данных новый факт с помощью цели ?- assert_new_fact(a(Дима)). потерпела бы фиаско, так как предикат a/1 в отличие от предиката b/1 является не динамическим, а статическим.
120