- •К.Є. Золотько, д.В. Красношапка
- •1. Теоретичні основи створення систем штучного інтелекту
- •1.1. Методи розв’язання задач
- •Розв’язання задач методом пошуку в просторі станів
- •Загальна схема алгоритму Харта, Нільсона і Рафаеля
- •Розв’язання задач методом редукції
- •Розв’язання задач дедуктивного вибору
- •Розв’язання задач, що використовують немонотонну логіку, імовірнісну логіку
- •1.2. Експертні системи
- •Експертні системи, засновані на правилах (пряме виведення – forward chaining)
- •Експертні системи, що ґрунтуються на логіці (зворотне виведення – backward chaining)
- •Модуль (компонент) пояснення
- •Модуль (компонент) набуття знань
- •Етапи проектування експертної системи
- •Відмінність експертних систем від традиційних програм
- •2. Основи програмування мовою Visual Prolog
- •2.1. Загальний огляд мови Пролог
- •2.2. Основні теоретичні відомості Основні визначення мови Visual Prolog
- •2.3. Структура програми, складеної мовою Visual Prolog
- •2.4. Предикати введення – виведення
- •2.5. Об’єкти даних
- •Завдання 1
- •2.6. Вбудовані механізми мови Пролог. Керування бектрекінгом
- •2.7. Організація циклів. Рекурсія
- •2.8. Використання динамічної бази даних
- •2.9. Рекомендації щодо створення програм мовою Пролог
- •Завдання 2
- •2.10. Рекурсивні структури даних
- •Структура даних типу дерево
- •Обходи дерева
- •Бінарний пошук на дереві
- •Сортування за деревом
- •Лексикографічне впорядкування
- •2.11. Списки
- •Info("Шевченко о.В.", ["Інформатика", "Чисельні методи"]).
- •Info("Нікольський а.С.", ["Комп’ютерна графіка"]).
- •Info("Рябчук м.В.", ["Фізика", "Хімія", "Астрономія"]).
- •Info("Рябчук м.В.", X), write (X), nl.
- •Ігри двох осіб із повною інформацією
- •Мінімаксний принцип
- •Реалізація деяких методів пошуку в просторі станів у мові Пролог
- •Завдання 3
- •Засоби програмування інтерфейсів у Visual Prolog 5.2
- •3.1. Створення найпростішого додатка
- •Додавання пункту меню
- •Додавання речення для реагування на вибір пункту меню
- •Використання діалогових вікон, створених користувачем
- •Завдання 4
- •Варіанти завдань
- •Тема 1. Консультативна інтерактивна експертна система з визначення оптимальної конфігурації пеом
- •Тема 2. Діагностична інтерактивна експертна система пошуку причини й усунення несправності кольорового телевізора lg cf-20f60k
- •Порядок пошуку причини й усунення несправності телевізора lg cf-20f60k
- •Тема 3. Консультативна експертна система для вибору породи собаки
- •Тема 4. Медична консультативна експертна система щодо вибору лікарських трав
- •Тема 5. Експертна система для визначення мінерального добрива
- •Тема 6. Консультативна інтерактивна експертна система, яка допомагає директору фірми в процесі прийняття кандидата на роботу
- •Тема 7. Консультативна експертна система прогнозу повені та необхідності евакуації населення міста
- •Тема 8. Діагностична медична експертна система
- •Список рекомендованої літератури
- •Посібник до вивчення курсу
Завдання 2
Розв'язати задачі, аналогічні поданим у завданні 1 (див. розд. 2.5), з урахуванням того, що родинне дерево з фактами повинне знаходитися в динамічній БД. Користувач має сам заповнити цю БД під час виконання програми, а потім записати її у файл. Треба забезпечити можливість у подальшому зчитувати її з файлу. Програма повинна мати меню, яке дозволяє виконувати команди користувача, наприклад:
заповнити БД;
записати БД у файл;
зчитати БД із файлу;
знайти прадіда;
закрити програму.
2.10. Рекурсивні структури даних
Рекурсивними можуть бути не тільки правила, а й структури даних. Пролог належить до тих мов програмування, у яких дуже зручно можна організовувати, описувати й реалізовувати дані рекурсивного типу. Тип даних буде рекурсивним, якщо він являє собою структуру, яка у своєму визначенні використовує структуру, подібну собі.
Найчастіше вживана рекурсивна структура – список, але ми його розглянемо пізніше. У цьому розділі ми зосередимо свою увагу на структурі даних типу дерево і на її використанні.
Структура даних типу дерево
Серед структур даних типу дерево можна виділити спеціальний клас найчастіше використовуваних дерев – бінарні дерева. Можна дати рекурсивне визначення бінарного дерева:
порожнє дерево – бінарне дерево;
кожний вузол бінарного дерева має не більше одного лівого бінарного піддерева і не більше одного правого бінарного піддерева.
Таку структуру даних у мові Пролог можна визначити за допомогою двох предикатів: treetype = tree(string,treetype,treetype) та empty. Останній використовують для позначення порожнього дерева. Тому структуру даних для задання бінарного дерева можна описати таким чином:
domains
treetype= tree(string, treetype,treetype);
empty
Наприклад, дерево зображене на рис. 8, можна описати так:
tree("Перро",tree("Грімм",tree("Гауф",empty, empty),
tree("Лондон" ,empty, empty)),
tree("Кіплінг", tree("Уайльд",empty, empty),
tree("Лагерлеф" ,empty, empty)))
Рис. 8. Приклад дерева
Зазначимо, що це не є прологівська фраза; це тільки складна структура даних.
Обходи дерева
Існує багато правил обходу дерев: прямий, зворотний, кінцевий і т. д. Розглянемо, наприклад, алгоритм прямого обходу.
1. Якщо дерево порожнє, тоді нічого не робити.
2. У противному разі обробити поточний вузол, потім обійти ліве піддерево обробленого вузла, а потім обійти праве піддерево обробленого вузла.
У мові Пролог цей алгоритм реалізують за допомогою двох фраз:
traverse(empty).
traverse(tree(X,Y,Z):- do something with X, traverse(Y),
traverse(Z).
Для практичної реалізації розглянемо програму, яка обходить дерево й виводить на екран значення, що містяться у вузлах дерева:
domains
treetype = tree(string, treetype, treetype);
empty()
predicates
print_all_elements(treetype)
clauses
print_all_elements(empty).
print_all_elements(tree(X,Y,Z)):- write(X), nl,
print_all_elements(Y),
print_all_elements(Z).
goal: print_all_elements(tree("Перро", tree("Грімм",
tree("Гауф", empty, empty),
tree("Лондон", empty, empty)),
tree("Кіплінг", tree("Уайльд", empty,
empty), tree("Лагерлеф", empty,
empty)))).
Для значної кількості задач інколи потрібно створити структуру даних типу дерево в пам'яті комп'ютера з подальшою її обробкою.
Один вузол дерева можна створити так:
create_tree(N, tree(N,empty,empty)).
Цей предикат можна інтерпретувати так: „Якщо N є елемент даних, то tree(N,empty,empty) – це вузл дерева, який містить цей елемент”.
Процес побудови дерева трохи складніший. Розглянемо фразу, яка містить предикат із трьома аргументами типу дерево. Він вставляє перше дерево як ліве піддерево другого дерева, використовуючи третє дерево як результуюче:
insert_left(X, tree(A, _ , B), tree(A,X,B)).
Припустимо, наприклад, що ми хотіли б вставити
tree('Грімм ' , empty, empty)
як ліве піддерево:
tree('Перро', empty, empty).
Це можна зробити, сформувавши запит
goal : insert_left(tree(' Грімм ',empty,empty),
tree('Перро ',empty,empty),T)
де T зразу ж набуде значення tree('Перро', tree(Грімм ',empty,empty), empty).
Отже, ми поетапно можемо побудувати дерево. Наведена нижче програма демонструє застосування запропонованого підходу для побудови дерева. На практиці елементи, розміщені у вузлах дерева, майже завжди беруть із зовнішнього файлу. Для виконання цієї програми необхідно у Visual Prolog вибрати в меню Project пункт New project, ввести ім’я проекту й ім’я файлу проекту, перейти на вкладку target, у списку UI Strategy вибрати Easywin, створити проект і скопіювати текст програми у файл із розширенням .pro, згенерований Visual Prolog'ом. Для запуску програми слід застосувати команду R із панелі інструментів.
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* Прості процедури побудови дерева. *
* create_tree(A, B) вставляє A в поле даних дерева B *
* insert_left(A, B, C) вставляє A як ліве піддерево B, *
* отримуючи дерево C *
* insert_right(A, B, C) вставляє A як праве піддерево B, *
* отримуючи дерево С *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
domains
treetype = tree(string, treetype, treetype);
empty()
predicates
create_tree(string, treetype)
insert_left(treetype, treetype, treetype)
insert_right(treetype, treetype, treetype)
clauses
create_tree(A, tree(A, empty, empty)).
insert_left(X, tree(A, _, B), tree(A, X, B)).
insert_right(X, tree(A, B,_), tree(A, B, X)).
goal
/* Спочатку створимо вузли (однорівневі дерева)... */
create_tree("Гауф", Ch), create_tree("Лондон", H),
create_tree("Грімм", Mi), create_tree("Уайльд", J),
create_tree("Лагерлеф", E), create_tree("Кіплінг", Me),
create_tree("Перро", Ca),
/* ... потім установимо зв'язки */
insert_left(Ch, Mi, Mi2), insert_right(H, Mi2, Mi3),
insert_left(J, Me, Me2), insert_right(E, Me2, Me3),
insert_left(Mi3,Ca, Ca2), insert_right(Me3, Ca2, Ca3),
/* ... і роздрукуємо результат. */
write(Ca3), nl.
Оскільки в мові Пролог ми не можемо змінити значення змінної, а можемо лише пов'язати змінну з якимсь значенням, ця програма містить так багато змінних.