Материал: Волченков Логическое программирование язык пролог 2015

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

'го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

Источник: https://studfile.net/preview/16708744/