Предмет:
Тип роботи:
Методичні вказівки
К-сть сторінок:
44
Мова:
Українська
слон) не підтвердився. Але, що трапиться, якщо ми поставимо запитання по-іншому?
?- більше(слон, мавпа). No
Таким чином, слони не більше, ніж мавпи. Отриманий результат зовсім не узгоджується з нашими уявленням про світ, але якщо подивитися на базу даних, то легко помітити, що в ній дійсно нічого не сказано про відносини між
слонами й мавпами. Однак, ми знаємо, що слони більше, ніж кінь, який у свою чергу більший, ніж віслюк, який більший за мавпу, тому слони також повинні бути більші, ніж мавпи.
Правильна інтерпретація негативної відповіді, даної Прологом, така: інформації, яка повідомлена системі, недостатньо для доказу того, що слон більший за мавпу. Якщо ми захочемо одержати позитивну відповідь на запит виду більше(слон, мавпа), то ми повинні забезпечити більш точний опис світу. Одним з можливих способів вирішення цієї проблеми є додавання відсутніх фактів, наприклад,
більше(слон, мавпа).
Для нашого маленького приклада це означає додавання ще 5 фактів. Однак набагато кращим рішенням буде додавання в програму нового відношення, що ми назвемо більше_2. Тварина X більша, ніж тварина Y, якщо це визначено як факт (перше правило) або існує тварина Z, для якої визначений факт, що
тварина X більша, ніж тварина Z, і може бути показано, що тварина Z більша, ніж тварина Y (друге правило). На Пролозі це запишеться так:
більше_2(X, Y) :- більше(X, Y).
більше_2(X, Y) :- більше(X, Z), більше(Z, Y).
Якщо в ланцюжку беруть участь не три, а більше число об'єктів, то прийде додати нові правила:
більше_2(X, Y) :- більше(X, Z1), більше(Z1, Z2), більше(Z2, Y).
більше_2(X, Y) :- більше(X, Z1), більше(Z1, Z2),
більше(Z2, Z3), більше(Z3, Y).
...
Ця програма довга й працювати буде далеко не завжди. Вона зможе переглядати базу даних тільки до певної глибини, що задається максимальною кількістю підцілей у правилах.
Тому скористаємося більш коректним й елегантним формулюванням. Ключова ідея тут - визначити відношення більше_2 за допомогою його самого. Тепер друге (і останнє!) правило виглядає так:
більше_2(X, Y) :- більше(X, Z), більше_2(Z, Y).
Таким чином, підсумкова програма буде мати вигляд
більше_2(X, Y) :- більше(X, Y).
більше_2(X, Y) :- більше(X, Z), більше_2(Z, Y).
Зверніть увагу на порядок підцілей у другому правилі: якщо їх поміняти місцями, то в більшості реалізацій мови Пролог виконання запиту до такої бази знань приведе до повідомлення про помилку, аналогічне наступному:
Якщо тепер у запиті використати предикат більше_2 замість більше, те програма буде працювати так, як і передбачалося:
?-більше_2(слон, мавпа). Yes
Інтерпретатор завжди переглядає базу даних зверху вниз. Тому він аналізує спочатку першу фразу процедури більше_2 і намагається уніфікувати кожен аргумент запиту з відповідним аргументом цієї фрази. Це відбувається за допомогою порівняння запиту з початком правила більше_2(X, Y) (тобто з його головою). Після цього двом змінним привласнюються значення: X = слон та Y = мавпа.
Після конкретизації змінної деяким термом це значення "закріплюється" за всіма випадками використання цієї змінної в правилі. Після уніфікації запиту із заголовком фрази інтерпретатор переходить до обробки цілей, що знаходяться в тілі цієї фрази.
У цьому випадку Пролог не може знайти в базі даних факту більше(слон, мавпа) і переходить до розгляду другого правила. Воно говорить, що для того, щоб одержати відповідь на питання більше_2(X,Y) (з фіксованими значеннями змінних, тобто більше_2(слон, мавпа)), Пролог повинен відповісти на два підпитання більше(X, Z) і більше_2(Z, Y), знову ж з відповідними значеннями змінних. Процес перегляду бази знань із самого початку повторюється доти, поки факти, що становлять ланцюжок між слон і мавпа, не будуть знайдені, а запит успішно оброблений.
Будь-яка рекурсивна процедура повинна включати принаймні по одній з нижче перерахованих компонентів.
1. Нерекурсивну фразу, що визначає правило, застосовуване в момент припинення рекурсії.
2. Рекурсивне правило, перша підціль якого виробляє нові значення аргументів, а друга - рекурсивна підціль- використовує ці значення.
1.8. Бази знань
Як ми вже відзначали, програма мовою Пролог, що містить факти й правила, становить базу знань. При розробці програм на Пролозі часто використовують вбудовані предикати, тобто предикати, обумовлені автоматично при ініціалізації інтерпретатора Прологу.
Вбудовані предикати використовуються так само, як й обумовлені користувачем предикати. Єдине обмеження - вбудований предикат не може бути головою правила або з'являтися у факті.
Одним з найчастіше використовуваних вбудованих предикатів є предикат not (заперечення). Цей предикат істинний, якщо його аргумент помилковий, і навпаки. Можна використати й іншу форму запису даного предиката \+.
Приклад
Якщо ми визначимо правило неправда(X) :- not(X). неправда1(X) :- \+(X).
то наступні запити будуть еквівалентні:
?- not(більше(собака, кінь)). Yes;
?- неправда(більше(собака, кінь)). Yes
Іншим часто використовуваним вбудованим предикатом є = (уніфікація):
=(X, Y). Цей предикат допускає більше зручну форму запису X = Y. Значення цього предиката істинно, якщо терми X й Y вдається уніфікувати.
На предикат not схожий вбудований предикат \=, що залежить від двох аргументів. Твердження X \= Y еквівалентно твердженню not(X = Y).
Іноді буває корисно використати предикати, про