Прості прийоми роботи з динамічними БД

 

У секції database декларуються предикати, що описують динамічну базу даних. Опис предикатів динамічної БД повинен передувати опису всіх звичайних предикатів.

У наведеній нижче програмі 6_1 розглянуто приклад використання явної динамічної бази даних, структура якої відповідає відношенню

Особа(Ім’я, Вік, Стать).

На основі явної динамічної БД, яка допускає модифікацію під час роботи, в програмі за допомогою правил визначені ще три неявні бази даних:

Чоловік (Ім’я, Вік), Жінка (Ім’я, Вік), Дитина (Ім’я, Вік, Стать)

Предикат реrson() можна використовувати так само, як і будь-які інші предикати. Відмінність лише у тому, що для нього, під час виконання програми, можливе додавання і видалення фактів. Факти, що додаються таким чином, зберігаються в оперативній пам’яті. На основі програми 6_1, розглянемо прості прийоми роботи з динамічними БД.

/* Програма 6_1 */

domains

name= string

age = integer

sex = m; f /* домени m і f складаються тільки з одного функтора */

database

реrson(name, age, sex)

predicates

male(name, age)

female(name, age)

child(name, age, sex)

clauses

male(Name, Age) :- person(Name, Age, m).

female(Name, Age) :- person(Name, Age, f).

child(Name, Age, Sex) :- person(Name, Age, Sex), Age<15.

Якщо запустити дану програму на виконання та сформувати до неї запит Goal: реrson(X, Y, Z), то Пролог відповість "ні" що викликане відсутністю даних в динамічні БД. Якщо ж тепер ввести послідовно дві цілі:

Goal: asserta(реrson(„Тарас”, 20, m))

Goal: asserta(реrson(„Світлана”, 21, f))

і знову ввести початковий запит, то отримаємо наступну відповідь:

X = „Світлана” Y=21 Z=fX = „Тарас” Y=20 Z=m

Одержана відповідь характеризує наявність в БД реrson() відомостей про дві особи, їх імена, вік та стать, хоча ніяких додаткових фактів в текст програми не вводилося. У цьому принципова відмінність динамічних БД, які організовуються Прологом в пам'яті ПК, окремо від основної Пролог-програми.

Занести інформацію про Тараса і Світлану в динамічну БД нам дозволив предикат asserta(). Особливість його роботи видно із порівняння двох цілей та результату запиту. Дані про Миколу вводилися першими, а потім дані про Світлану. В отриманій відповіді першими наведено дані про Світлану. Це пов'язано з тим, що предикат asserta(реrson(„Світлана”, 21, f)) додав дані про Світлану в початок динамічної БД. Додамо в БД інформацію ще про дві особи, послідовно вводячи ще дві цілі:

Goal: assertz(реrson(„Степан”, 9, m))

Goal: asserta(реrson(„Ольга”, 8, f))

Якщо тепер сформулювати запит про видачу всієї інформації, що зберігається в динамічній БД person(), то відповідь на нього буде одержана в наступній формі:

Goal: реrson(Name,Age,Sex),Name = „Ольга” Age=8 Sex=fName = „Світлана” Age=21 Sex=fName = „Микола” Age=20 Sex=mName = „Степан” Age=9 Sex=m

Із співставлення донаних цілей і результатів запиту видно, що один з нових фактів поміщений в початок динамічної БД, а другий – в кінець, що пов’язане з відмінністю в роботі предикатів asserta() і assertz().

З елементами динамічної БД Пролог може виконувати всі операції, допустимі для фактів аналогічної структури. Їх можна шукати, уніфікувати, використовувати у вигляді підзадач правил і т.д. Так, в програмі 6_1 динамічна БД входить у вигляді підцелі трьох правил формування неявних БД. Використовуючи предикати неявних БД, можна сформувати запити про дані про чоловіків, жінок або дітей:

Goal: male(Name, Age)

Name = „Тарас” Age=20

Narne = „Степан” Age=9

Goal: female(Name, Age)

Name = „Світлана” Age=21

Name = „Ольга” Age=8

Goal: child(N, A, S)

N = „Ольга” A=8 S=f

N = „Степан” A=9 S=m

Або сформувати на їх основі будь-які інші, прості або складові, запити.

Якщо потрібно буде видалити з динамічної БД який-небудь факт, то для цього слід скористатися предикатом retract(). Наприклад, для видалення відомостей про „Світлану” слід ввести наступну ціль:

Goal: retract(реrson(„Світлана”, _, _))

При необхідності скоректувати який-небудь елемент динамічної БД його слід видалити з бази даних, а потім додати в динамічну БД новий модифікований елемент. Зокрема, для того, щоб змінити вік „Миколи” на один рік, треба ввести таку складну ціль:

Goal: реrson(„Микола”, OldAge, Sex, Person), retract(реrson(„Микола, _ ,_)), NewAge = OldAge + 1, !, asserta(реrson(„Микола”, NewAge, Sex, Person)),

яка видалить старий факт і додасть в динамічну БД модифікований факт. Результат проведених перетворень БД можна одержати, як відповідь на наступний запит:

Goal: реrson(Name,Age,Sex)Name = „Микола” Age=21 Sex=mName = „Ольга” Age=8 Sex=fName = „Степан” Age=10 Sеx=m

Динамічна БД може бути збережена в текстовому файлі за допомогою виклику предиката save() з ім'ям текстового файлу, в якості параметру. Наприклад, після виконання цілі:

Goal: save(„person.dba”)

файл „person.dba” буде схожий на звичайну програму на Пролозі з фактами у кожному рядку. Такий файл може бути пізніше знову завантажений в пам'ять, за допомогою предикату consult():

Goal: consult(„person.dba”).

Завантаження виконається успішно лише в тому випадку, якщо програма у файлі не містить помилок. За наявності помилок зчитування даних із файлу до динамічної БД не відбудеться.

Раніше вже не раз наголошувалося, що будь-яка програма на Пролозі – це набір фактів і правил, які є своєрідною базою даних, на якій Пролог виконує логічний висновок. У свою чергу, динамічні бази даних – це набір фактів, який може змінюватися при роботі програми.

З цих двох умов випливає найважливіший висновок: Пролог допускає зміну програм під час їх виконання! І ці зміни можна виконувати, використовуючи динамічні бази даних.