Лабораторная работа 9
Работа со сложноструктурированными базами данных

       Цель работы:
  1. Знакомство с организацией сложноструктурированных БД в Турбо-Прологе.
  2. Закрепление знаний по описанию сложных структур данных.
  3. Получение навыков составления Пролог-программ для работы с БД.
  4. Разработка собственной информационно-запросной системы на Прологе.

1. Задание на лабораторную работу

       Требуется разработать информационно-запросную систему для некоторой предметной области. В качестве примера можно использовать приведенное ниже описание логической модели данных предметной области "семья". Для решения поставленной задачи необходимо:
  1. Сформировать и описать в программе все необходимые структуры данных.
  2. Описать структуру динамической БД.
  3. Описать и определить предикаты неявных БД.
  4. Составить описания и включить в программу процедуры, реализующие ряд описанных ниже действий над базами данных.
  5. Разработать внешний (экранный) интерфейс по работе с программой. При выполнении задания может быть рассмотрена любая другая предметная область, соответствующая по сложности структур, набору процедур и действий над БД описанному ниже примеру.

2. Описание логической модели данных

       Данная лабораторная работа развивает навыки представления структурных объектов данных и управления ими. Она показывает, что Пролог является естественным языком запросов к базе данных и как с его помощью переходить к формированию простейших баз знаний.

       Как УЖС отмечалось ранее, одним из способов представления БД на Пролом может быть представление БД в виде множества фактов. Например, в базе данных о семьях каждая семья может описываться одним фактом. При этом в составе любой семья можно выделить три ее компоненты: муж, жена и дети. Исходя из этого, в предметной области "семья" могут быть выделены три объекта, которые описываются отношением
Семья(Муж, Жена, Дети)
       Поскольку количество детей в разных семьях может быть разным, то объект Дети целесообразно представить в виде списка, состоящего из произвольного числа элементов:
Дети = [ Ребенок!, Ребенок2, . . . , РебенокN ]
       Каждого члена семьи в свою очередь можно описать структурой, состоящей из четырех компонент: имени, фамилии, даты рождения и вила деятельности. Т.е. представить в виде:
ЧленСемьи(Имя , Фамилия, ДатаРождения, Деятельность)
       При этом дата рождения также представляется структурой, объединяющей в своем составе три компоненты: число, месяц и год рождения:
Дата(Число, Месяц, Год)
       Особый интерес представляет информация о виде деятельности, которая может содержать сведения о том работает, учится или не работает какой-либо член семьи. Причем в том случае, если человек работает, следует иметь данные о месте его работы, должности и окладе. Если учится, то следует указать место учебы. Если не работает, то надо иметь об этом информацию. Таким образом, вид деятельности для каждого из членов семьи может быть описан одной из возможных структур:
Работает(Где, Кем, Оклад) или УчитсяГде) или НеРаботает
       Графически информацию о каждой семье можно представить в виде структуры, приведенной на рис.6


Рис.6. Структурированная информация о семье.


       Информация о семье, изображенной на рис.6, является экземпляром отношения Семья и может быть занесена в базу данных в виде факта (утверждения):
семья ( членсемьи( Иван. Ким, дата(8,март, 1949), работает(АО,шеф,500) ).
        членсемьи( Лена, Ким, дата(3,май, 1951), неработает),
      [ членсемьи( пат,фокс, дата(5,май,1973), неработает),
        членсемьи( Саша, Ким, дата(1,июнь,1983), учится(школа) ) ]   ).
       Тогда БД будет состоять из последовательности фактов, подобных этому, и описывать все семьи, представляющие интерес для нашей программы.

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


Рис.7. Описание объектов по их структурным свойствам.
       Так, в запросах к БД можно ссылаться на всех Ивановых с помощью терма
семья( членсемьи( _, Иванов, _, _ ), _, _ )
       Символы подчеркивания означают различные анонимные переменные, значения которых нас не заботят. Ссылаться на все семьи с тремя детьми позволяет терм:
семья( _, _, [_,_, _] )
       Чтобы найти всех замужних женщин, имеющих по крайней мере троих детей, можно задать вопрос:
семья( __, членсемьи(Имя,Фамилия,_,_),[_,_,_ |_]).
       Основным моментом в этих примерах является то, что указывать интересующие нас объекты можно не только по их содержимому, но и по их структуре.

3. Получение структурированной информации из базы данных

       Можно создать набор процедур, который делал бы взаимодействие с нашей БД более удобным. Такие процедуры являлись бы частью пользовательского интерфейса. Вот некоторые полезные процедуры для рассматриваемой БД:
муж( X) :- семья( X, _, _).
жена( X) :- семья (_, X, _).
ребенок( X) :- семья( _,_, Дети),принадлежите X, Дети).  /* принадлежит элемент списку */'
существует (Членсемьи) :- муж( Членсемьи);     	         /* Любой член семьи в БД к/
         жена( Членсемьи);
         ребенок ( Членсемьи).
датарождения(Членсемьи(_,_Дата,_)Дата).
доход( Членсемъи(_,_,_,работает(_,S) ),S) :- !.          /* Доход работающего */
доход( Членсемьи( _,_,_,_), 0).                          /* Доход неработающего */
принадлежите (X, [X п L ].
принадлежит (X, [Y п L ] :- принадлежит( X, L).
       Этими процедурами можно воспользоваться, например в следующих запросах в базе данных:
Запрос
Цель
Найти имена и фамилии всех людей из базы данных
существует( членсемьи( Имя, Фамилия, _, _)).
Найти всех детей, родившихся в 1983 году
ребенок(X), датарождения( X, дата( _,_, 1983) ).
Найти всех работающих жен.
жена( членсемьи( Имя, Фамилия,_, работает(_,_))).
Найти имена и фамилии людей, которые не работают и родились до 1963 года
существует( членсемьи( Имя, Фамилия,дата(_,_,Год) неработает)).Год < 1963.
Найти людей, родившихся до1950 года, чей доход меньше, чем 1000
существует( Членсемьи), датрождения( Членсемьи,дата(_,_,Год)). Год < 1950.доход(Членсемьи. Доход).Доход <1000.
Найти фамилии людей, имеющих по крайней мере трех детей
семья(членсемьи(_, Фамилия,_,_), _,[_,_,_|_]).
       Для подсчета общею дохода семьи полезно определить сумму доходов людей из некоторого списка в виде двухаргументного отношения:
общий( Список_Людей, Сумма_их_доходов)
для которого можло написать процедуру вида:
общий( [], 0).                        /* Пустой список людей +/
общий([Человск 1 Список], Сумма) :-
доход(Человек, S),                    /* S - доход 1-ого человека */
общий( Список, Sn),                   /* Sn - сумма доходов оста:1ьных */
Сумма is S + Sn.
Теперь общие доходы всех семей могут быть найдены с помощью запроса:
семья( Муж, Жена, Дети), общий( [Муж, Жена, Дети], Доход).
       Пусть отношение длина подсчитывает количество элементов списка, как это было в работе, посвященной спискам. Тогда мы можем найти все семьи, которые имеют доход на члена семьи, меньший, чем 2000, при помощи запроса:
семья( Муж, Жена, Дети), общий( [Муж, Жена п Дети], Доход), длина([Муж, Жена пДети], N), Доход/N < 2000.
       Задание 1.
Напишите запросы для поиска в БД: а) семей без детей: b) всех работающих детей; с) семей, где жена работает, а муж нет; d) всех детей, разница в возрасте родителей которых составляет не менее 15 лет. Запросы и результат их выполнения привести в отчете по работе.

4. Абстракция данных и построение баз знаний

       Абстракцию данных можно рассматривать как процесс организации различных фрагментов информации в единые логические единицы. При этом каждой такой логической единице придается некоторая концептуально осмысленная форма. Любая информационная единица должна быть легко доступна в программе. В идеальном случае все детали реализации исходной структуры должна быть невидимы пользователю. И самое главное - дать ему возможность использовать информацию не думая о деталях ее действительного представления.

       Одним из способов реализации этого принципа является применение неявных баз данных, а также привлечение дополнительных знаний о правилах построения этих баз на основе структуры исходных данных.

       В рассматриваемом примере каждая семья - это набор некоторых фрагментов информации. Все они объединены в естественные информационные единицы такие, как членсемьи или семья, и с ними можно обращаться как с едиными объектами.

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

       Для исходной БД такими новыми отношениями (неявными БД) могут являться:
Отец(ИмяРебенка,ИмяОтца), МатыИмяРебенка, ИмяМатсри), Сестра-Брат(Имя1, Имя2).
       Используя эти отношения, а также знания о родственных связях между людьми в обществе, можно сформировать базу знаний о родственниках, которая, например может содержать следующий набор отношений:
Родитель(ИмяРебенка, ИмяРодителя), Бабушка( ИмяВнука, ИмяБабушки). Дедушка(ИмяВнука, ИмяДедушки),
...
Предок( Кто, Чей).
       Задание 2.
Добавьте в исходную программу описание новых отношений и сформируйте процедуры для их определения. В исходную БД добавьте ряд фактов для семей, чтобы введенные родственные связи существовали, и выполните ряд произвольных запросов содержание которых и результат выполнения привести в отчете по работе.

5. Содержание отчета по лабораторной работе

       Отчет по лабораторной работе должен соответствовать требованиям основного задания на работу и включать результаты выполнения заданий 1 и 2.