Page 20 - 4800
P. 20
all_colleague(name, name, object)
query
do_answer(namе)
goal
query.
clauses
colleague(Man1,Man2):-work(Man1,X), work(Man2,X), Man1<>Man2.
all_colleague(X, Y, Z):- colleague(X,Y), Z=labour.
all_colleague(X, Y, Z) :- unite(X, Y, Z).
all_colleague(X, Y, Z) :- unite(Y, X, Z).
unite(„Возняк”, „Денега”, labour ).
unite(„Петренко”, „Скрипник”, project("New system",ics)).
unite(„Козлов”, „Петренко”, labour).
unite(„Савюк” , „Петренко”, hobby(sport)).
work(„Грищенко”, 101).
work(„Кардаш”, 111).
work(„Петренко”, 101).
work(„Скрипка”, 101).
work(Man1, N):-unite(Man1, Man2, labour), work(Man2, N).
query:- write(„Введіть прізвище –> ”), readln(Who), do_answer(Who).
do_answer(X):- colleague(X, Y), write(„ „, X, ”колега „, Y), nl, fail.
Два предикати цієї програми query і do_answer(…) дозволяють формувати запит
і одержувати на нього відповідь. Програма містить внутрішню мету у вигляді
предиката query, що видає підказку, забезпечує ввід та уніфікацію змінної Who.
Предикат do_answer(...) організовує запит на пошук товаришів по службі введеного
службовця.
2.5 Організація повторюваних процесів
При виконанні запитів програма послідовно звертається до фактів і правил. При
цьому правила часто вимагають, щоб задачі типу пошуку елементів у базі, вводу або
виводу даних виконувалися багаторазово. Однак у Пролозі немає можливості
безпосереднього завдання ітераційного процесу, тобто не реалізовані синтаксичні
конструкції типу FOR, WHILE або REPEAT.
Існує два способи побудови правил, що виконують ту саму задачу кілька разів.
Це повторення, що використовує повернення, і рекурсія, що використовує виклик
процедури самої себе.
Повторення реалізується з використанням методу відкату після невдачі, коли
здійснюється повернення до останньої підмети, що має альтернативне рішення,
реалізація альтернативи і чергове повернення. Тому пошук з поверненням можна
використовувати для виконання повторюваних процесів. Прикладом побудови правила,
що використовує повторення, є предикат do_answer() у програмі 2.3.
Але якщо цей підхід застосувати до предиката query тієї ж програми, тобто
штучно викликати стан невдачі, додавши предикат fail у вигляді останньої підмети
правила, то ніякого повторного запиту на введення ми не одержимо. Пояснюється це
тим, що предикати вводу не є альтернативами, тобто не мають альтернативних рішень,
а предикат do_answer() всі альтернативні рішення одержав, тобто мета query є істинною
і рішення задачі закінчується.
Для того що забезпечити багаторазовий ввід даних, необхідно, щоб відкат
виконувався до деякого предиката, що має альтернативне рішення, з одного боку, і щоб
це рішення було б постійно істинним, з іншого боку. При невиконанні останньої умови
відкат може відбутися до ще більш ранньої підмети і не забезпечить повторення
потрібної нам групи дій.
Використовуючи найпростішу рекурсію, процедура завдання предиката для
правила повтору, обумовленого користувачем, може мати вигляд:
repeat.
repeat :- repeat.
Перший рядок – це факт, що завжди успішний і забезпечує істинність предикату
repeat. Але, оскільки для цього предиката існує ще одне правило, то покажчик відкату
20