Лабораторная работа 7
Способы представления баз данных в Пролог-программах
2. Представление отношений в виде фактов
Модель любой предметной области может быть представлена совокупностью объектов с указанием связей между ними. Используя реляционный подход к построению БД, любой объект может быть интерпретирован как отношение, достаточно полно описывающее некоторый аспект предметной области и устанавливающее функциональную зависимость атрибутов этого отношения от некоторого ключевого атрибута. Для рассматриваемого примера таким отношением может бытьРАБОТА (ИМЯ_СТУЖАЩЕГО, ОТДЕЛ, ДОЛЖНОСТЬ, ОКЛАД),где в качестве ключа может рассматриваться атрибут - ИМЯ_СЛУЖАЩЕГО. Отношение представляет собой множество кортежей, каждый из которых соответствует определенному экземпляру объекта предметной области и может быть представлен в виде целостного информационного элемента.
work1 ("Петров", 101, "оператор", 20000).Запрос work1 (Name, 101,Post,Salary) позволяет отыскать всех служащих 101 отдела.
work1 ("Павлов", 211, "начальник", 71000).
work1 ("Иванов", 101, "менеджер", 71500).
3. Представление атрибутов в виде фактов
Вместо того, чтобы записывать факты, содержащие целостные информационные элементы, можно использовать в качестве фактов отдельные атрибуты (т.е. свойства) этих информационных элементов. В случае необходимости Данные атрибуты можно собрать в единое целое при помощи правила. Один из атрибутов должен выступать в роли ключа, объединяющего все остальные свойства. Атрибут ИМЯ_СЛУЖАЩЕГО можно использовать в качестве ключа для БД work(). Первый экземпляр объекта РАБОТА можно представить таким образом:Все атрибуты для конкретного служащего, совокупность которых представляет собой определенный экземпляр объекта предметной области, можно объединить при помощи правила:office ("Петров". 101). /* отдел */ post ("Петров", "оператор"). /* должность */ salary ("Петров", 20000). /* оклад */
work2 (Name,Office,Post,Salary) :- office ( Name, Office ), post ( Name, Post), salary ( Name, Salary ).Это правило определяет неявную базу данных того же вида, что и приведенная ранее явная база данных work1(). Для этого правила можно воспользоваться предыдущим запросом, который даст те же результаты, что и ранее.
prize ( Name, 1000 ) :- office ( Name, 101 ).Для некоторых служащих можно ввести дополнительный атрибут "стаж_работы" и некоторый набор фактов, его описывающий:
work_time ( "Петров", 2 ).Добавление новых атрибутов "премия" и "стаж_работы" никак не повлияет на приведенное выше правило work2().
work_time ( "Иванов", 1 ).
4. Представление базы данных в виде списке, структур
Базу данных можно также считать потоком целостных информационных элементов, что представляется на языке Пролог в виде списка структур. Каждый элемент списка - это целостный информационный элемент:[ work ( "Петров". 101. "оператор" , 20000) , work ( "Павлов", 211, "начальник", 71000) , work ( "Иванов", 101, "менеджер" , 71500) ]Интересно отметить, что при таком подходе к структуре базы данных поток целостных информационных элементов lie нужно включать в текущую программу. Он может существовать лишь как аргумент запроса, входящий в различные подцели, которые обрабатывают этот поток.
record ( work(Name.Office.Post.Salary). [work(Name.Office.Post.Salary) п_]).Описание процедуры record() аналогично процедуре member(). С использованием процедуры record() можно составить запрос о всех служащих отдела 101. Во втором аргументе этого запроса полностью содержится вся база данных.
record ( work(Name,Office,Post,Salary), [work(_,_,_,_) п Tail]) :- record ( work(Name,Office,Post,Salary), Tail).
Задание 2.
- Goal:
- record(work(Name,101,Post,Salary), [work("",101,"оператор",20000), work("",211,"начальник",71000), work("",101,"менеджер",71500)]).
5. Представление базы данных в виде линейной рекурсивной структуры
Еще одним из способов представления в памяти ЭВМ записей баз данных является использование рекурсивных структур, в которых один из ар1ументов каждой записи указывает на следующую запись. Рекурсивные структуры - аналог односвязных списков в других языках программирования, но работать с такими структурами в Прологе легче, так как он берет на себя все действия по обработке указателей.work3( "Петров", 101, "оператор", 20000,Заметьте, что уровень вложенности у каждой новой записи будет большим, чем v предыдущей. В пятом поле последней записи содержится слово "end", которое означает, что больше записей нет. Следует отметить, что дополнительный аргумент структуры, указывающий на следующие записи базы данных, сам имеет структуру этой записи. Т.е. структура записи определяется сама через себя: Служащий (Имя , Отдел, Должность , Оклад , Служащий).
work3( "Павлов", 211, "начальник". 71000,
work3( "Иванов", 100, "менеджер". 71500, end)))
1 запись 2 запись 3 запись конец записей
record( work(Name,Office,Post,Salary), work3(Name, Office, Post, Salary, NextRecord)).Используя процедуру record(), можно сформировать внешнюю цель для запроса по отысканию всех служащих 101 отдела, при условии, что вторым аргументом процедуры будет вся база данных.
record( work(Name,Office,Post, Salary), work3( _,_,_,_, NextRecord)) :- work3 ( work(Name,Office,Post,Salary),NextRecord).
Ответ на этот запрос будет получен в виде
- Goal:
- record (work(Name,101,Post,Oкл), work3("Петров",101,"оператор",20000, work3("Павлов",211,"начальник"71000,work3("Иванов",l00, "менеджер",71500,end))).
Name=Петров,Аналогичный вариант запроса реализован как внутренняя цель print_101 программы 16.
Post=onepaтop,
Salary=20000
Name=Иванов,
Post=менеджер,
Salary=71500
/* Программа 16 *)Эта программа работает с БД work3(), представленной в виде линейной рекурсивной структуры.
- domains
- name = symbol
office = integer
worker = work(name,office)
/* описание рекурсивной структуры */
work3 = work3(name,office,work3) ; end- predicates
- print_10l
record( worker, work3 )- goal
- print_101 clauses record( work(N,O) , work3(N,0,_) ).
record( work(N,0) , work3(_,_,T) ) :- record( work(N,0) ,T).
print_101:- write(" Сотрудники 101 отдела"),nl.
record ( work(N,101), wоrkЗ("Петров",101, work3("Павлов",211, workЗ("Ивaнов",101,end)))), write(n),nl, fail.
6. Представление базы данных в виде двоичного дерева
Можно еще более усовершенствовать метод представления данных в виде рекурсивной структуры, если преобразовать структуру work3() в структуру типа двоичное дерево. Это достигается путем введения в структуру записи БД еще одного дополнительного аргумента, который указывает на предыдущую запись.Переменная LeftTree описывает ветвь дерева, которая содержит все целостные информационные элементы, стоящие (по алфавиту) перед текущим элементом. Переменная RightTree описывает ветвь дерева, охватывающую все целостные информационные элементы, расположенные согласно алфавиту, после данного элемента. ~ Ввиду того, что БД отсортирована, целостный информационный элемент, содержащий вес сведения о Павлове, является самым верхним узлом дерева, а саму БД, представленную в виде двоичного дерева, можно записать следующим образом:Павлов, … / \ Иванов, ... Петров, ... / \ / \ end end end endwork4( LeftTree, Name,Office,Post,Salary, RightTree)
work4 ( work4( end, "Иванов", 101,"менеджер",71500, end ), "Павлов",211,"начальник",71000, work4( end,"Петров", 101,"оператор", 20000,end),)Версия процедуры record() для доступа к целостному информационному элементу БД, представленной в виде двоичного дерева, будет базироваться на трех правилах:
record ( work(Name,Office,Post,Salary), work4(LeftTree, _,_,_,_, __)):- record ( work(Name, Office, Post, Salary), Let: Tree ).Теперь процедура record() определена, и можно написать запрос, позволяющий найти всех служащих отдела 101. Вторым аргументом запроса является целиком вся база данных.
record { work(Name,Office,Post,Salary), work4( _, Name.Office.Post.Salary, _) ).
record ( work(Name,Office,Post,Salary), work4(_, _,_,_,_, RightTree) ) :- record ( work(Name,Office,Post,Salary), RightTree ).
Ответ на запрос будет тот же самый, что и в предыдущих случаях. Одним из интересных свойств представления в виде двоичного дерева является то, что процедура record() всегда будет выдавать целостные информационные элементы, образующие дерево, в отсортированном порядке. Это иллюстрирует запрос
- Goal:
- record ( work(Name, 101,Post, Salary),
work4 (
work4( end, "Иванов", 101, "менеджер",71500. end ), "Павлов",211,"начальник",71000, work4( end, "Петров", 101,"оператор",20000,end). ) )
Задание 4.
- Goal:
- record ( OneRecord,
work4 (
work4( end, "Иванов", 101, "менеджер",71500, end ), "Парлов",211,"начальник",71000, work4( end,"Петров", 101 ."оператор", 20000,end),)
OneRecord = work("Иванов"10l,"onepaтop",20000);
OneRecord = work("Павлов",211, "начальник", 71000);
OneRecord = work("Петров",101," менеджер ",71500);
7. Сравнение разных видов представления базы данных
Наиболее важным различием между описанными формами представления БД является то, что для доступа к данным в каждом случае требуется свой алгоритм.8. Несколько полезных процедур работы с бинарными деревьями
Эффективность работы с БД в виде двоичных деревьев во многом определяется знаниями процедур их создана и преобразования. Рассмотрим ряд процедур, оперирующих с двоичными деревьями, описываемыми структурами видаtree( Left , Root , Right ),где Left - левое поддерево, каждый элемент которого имеет структуру, аналогичную tree(),
insert( end, X, tree( end, X, end ) ).Построение бинарного дерева из списка. Процедуру insert() можно использовать для построения упорядоченного дерева из списка. Процедура, обеспечивающая преобразование списка в упорядоченное дерево, будет иметь вид:
insert( tree(Left, Root, Right ), X, tree(LenNew,Root,Right) ) :- X < Root, insert( Left, X, LeftNew ).
insert( tree(Left,Root,Right), X, tree(Left.Root,RightNew) ) :- X > Root, insert( Right, X, RightNew ).
list_to_tree([], end ).Построение отсортированного списка из дерева. Для решения этой задачи можно воспользоваться упорядоченным бинарным деревом и объединением списков.
list_to_tree([HпT],AllTree) :- list_to_tree( T, Tree), insert(Tree, H, AllTree).
tree_to_list( end , [] ).Рассмотрим пример использования этих процедур в Пролог-программе, работающей с базами данных разных структур и преобразующей эти структуры.
tree_to_list( tree(Left,Root,Right), List ) :- tree_to_list( Left, L1), tree_to_list( Right, L2), append( L1, [Root п L2], List).
/* Программа 17 */Использование описанных выше процедур позволяет как модифицировать базы данных, так и осуществлять их структурные преобразования. Программа 17 даст возможность исследовать простейшие преобразования над базами данных.
- domains
- worker = symbol
listworker = worker*
tree = tree(tree,worker,tree) ; end- predicates
- db1( tree )
db2( listworker )
record( worker, tree )
append( listworker, listworker, listworker)
insert( tree, worker, tree)
list_to_tree( listworker, tree )
tree_to_list( tree, listworker)
goal1
goal2
goal3
goal4
goal5
goal6
goal7
goal8- clauses
- goal1 :- db1(DB), write(DB).
goal2 :- db1(DB), record(R,DB), write(R), nl, fail.
goal3 :- db1(DB), write("введи элемент "), readln(El), insert(DВ ,E1,DBnew), write(Dbnew).
goal4 :- dbl(DB), write("введи элемент "), readln(El), insert(DB,El,DBnew), record(R,DBnew), write(R), nl, fail.
goal5 :- db2(List), list_to_tree(List,Tree), write(Tree).
goal6 :- db2(List), list_to_tree(List,Tree), record(R,Tree), write(R), nl, fail.
goal7 :- dbl(Tree), tree_to_list(Tree,List), write(List).
goal8 :- db2(List), write(List), nl.
list_to_tree(List,Tree). write(Tree), nl,
tree_to_list(Tree,NewList), write(NewList), nl.
insert( end, X, tree(end, X,end) ).
insert( tree(L,Root,R). X, tree(LNew,Root.R)) :- X < Root.
insert(L,X, Lnew ).
insert( tree(L,Root,R). X, tree(L,Root,RNew)) :- X > Root.
insert( R,X, RNew).
list_to_tree( [] , end ).
list_to_tree([HпT], AllTree) :- list_to_tree( T, Tree ),
insert( Tree, H, AllTree ).
tree_to_list( end , [] ).
tree_to_list(tree(L,Root,R),List) :- tree_to_list( L, L1),
tree_to_list( R, L2),
append( L1, [ Root п L2 ], List ).
record( R, tree(LeftTree, _,_)):- record( R, LeftTree).
record( R, tree( , R,_) ).
record( R, tree( _, _,RightTree)):- record( R, RightTree).
append( [], L2, L2 ).
append( [HпL1], L2. [H п L3]) :- append(L1, L2, L3).
dbl( tree( tree(end,a,end), c, tree(end,e,end) ) ).
db2( [ c, e, a ] ).
9. Содержание отчета по лабораторной работе
Отчет по лабораторной работе должна содержать: