Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
49
Добавлен:
05.03.2016
Размер:
1.28 Mб
Скачать

4.4 Використання відкату після невдачі при використанні внутрішньої мети для організації найпростішого інтерфейсу виводу

Якщо найпростіший інтерфейс виводу буде реалізовано як внутрішню мету програми, то внутрішні уніфіковані процеси Турбо-Прологу закінчать пошук рішення відразу після першого успішного обчислення мети. Для пошуку всіх значень Пролог-програма повинна змусити повторно працювати внутрішні засоби уніфікації Турбо-Прологу.

Одним зі способів реалізації даної задачі є використання методу відкату після невдачі, що використовує предикат fail. Приклад використання цього предиката демонструє програма 4.3.

/* програма 4.3 */

include „lab3_3.рrо”

predicates

query

do_answer(namе)

goal

query.

clauses

query:- makewindow(2,7,15, „Визначення колег”, 18, 0, 6, 50), cursor(1, 10), write(„Введіть прізвище –> ”), readln(Who), makеwindow(1,7,15, „Колеги”, 1,50,22,29), do_answer(Who).

do_answer(X):- colleague(X, Y), write(„ „, X, ”колега „, Y), nl, fail.

Два предикати цієї програми дозволяють формувати запит і одержувати на нього відповідь. Текстова підстановка файлу програми 3.3 з лабораторної роботи №3 забезпечує доступ до всіх предикатів і бази даних.

Таким чином дана програма може бути прикладом інтерфейсу для вводу-виводу даних програми 3.3.

Програма містить внутрішню мету у виді предиката query, що створює на екрані вікно вводу даних, видає підказку, забезпечує ввід та уніфікацію змінної Who, а також формує вікно виводу даних.

Предикат do_answer(...) організовує запит на пошук товаришів по службі введеного службовця. Дії, виконувані системою по даному запиту, аналогічні першим 11 крокам, приведеним на рис.3.4. Але на 11 кроці система не буде здійснювати примусове повернення, і рішення задачі зупиниться.

Щоб цього не відбулося в програму введено предикат fail, що завжди викликає стан невдачі, та змушує систему виконувати, відкат після невдачі до попередньої доведеної підцілі, тобто фактичне продовження функціонування програми в режимі, аналогічному до приведеного на рис.4.4.

4.5 Зміст звіту по лабораторній роботі

Звіт по лабораторній роботі повинний містити:

1. Результати трасування програми 4.1 для трьох запитів, описаних у параграфі 1 даної лабораторної роботи.

2. Результати дослідження програми 4.3 при наявності і відсутності предиката fail у програмі.

3. Модифікований варіант програми 4.3 для випадку, коли вікно виводу займає цілий екран, а вікно вводу присутнє на екрані тільки на момент вводу.

4. Список, призначення та короткий опис найпростіших предикатів Турбо-Прологу для вводу-виводу даних різного типу.

5. Індивідуальне завдання.

Лабораторна робота №5 Керування ходом виконання Пролог-програм

Ціль роботи:

1. Ознайомлення з діями предикатів невдачі (fail) і відсікання (cut).

2. Вивчення методів організації повторного виконання групи задач.

3. Знайомство зі способом побудови меню.

4. Керування обмеженням простору пошуку з використанням відсікання.

5.1 Організація повторюваних процесів

При виконанні запитів програма послідовно звертається до фактів і правил. При цьому правила часто вимагають, щоб задачі типу пошуку елементів у базі, вводу або виводу даних виконувалися багаторазово. Однак у Пролозі відсутня можливість безпосереднього завдання ітераційного процесу, тобто не реалізовані синтаксичні конструкції типу FOR, WHILE або REPEAT.

Існує два способи побудови правил, що виконують ту саму задачу кілька разів. Це повторення, що використовує повернення, і рекурсія, що використовує виклик процедури самої себе.

Повторення реалізується з використанням методу відкату після невдачі, коли здійснюється повернення до останньої підмети, що має альтернативне рішення, реалізація альтернативи і чергове повернення. Тому пошук з поверненням можна використовувати для виконання повторюваних процесів. Прикладом побудови правила, що використовує повторення, є предикат do_answer() у програмі 4.3.

Але якщо цей підхід застосувати до предиката query тієї ж програми, тобто штучно викликати стан невдачі, додавши предикат fail у виді останньої підмети правила, те ніякого повторного запиту на введення ми не одержимо.

Завдання 1.

Викличте програму 4.3 (запишіть у файл lab5.pro), додайте fail у кінець опису query і, запустивши програму на виконання, переконайтеся що процес не повторюється. Пояснюється це тим, що предикати формування вікна і вводу не є альтернативами, тобто не мають альтернативних рішень, а предикат do_answer() всі альтернативні рішення одержав, тобто мета query є щирою і рішення задачі закінчується.

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

Використовуючи найпростішу рекурсію, процедура завдання предиката для правила повтору, обумовленого користувачем, може мати вигляд:

repeat.

repeat :- repeat.

Перший рядок – це факт, що завжди успішний і забезпечує щирість предикату repeat. Але, оскільки для цього предиката існує ще одне правило, то покажчик відкату встановлюється на перший repeat. Другий рядок – це правило, що використовує самовиклик. Правило (другий repeat) викликає підмету (третій repeat), і цей виклик здійснюється успішно, тому що факт (перший repeat) відповідає підметі. Отже, правило також завжди успішне. Предикат repeat буде успішно обчислюватися при кожній новій спробі його викликати після відкату. Таким чином, repeat – це рекурсивне правило, що ніколи не буває неуспішним.

Завдання 2.

Введіть у програму опис предикату repeat. Вставте звертання до цього предиката в якості першої підмети правила query. Запустіть на виконання програму.

Тепер з'явилася можливість повторного вводу, але немає ознаки закінчення і єдиний варіант виходу з програми – це Ctrl+Break. Але для того, щоб сформувати ознаку закінчення повторень, необхідно вияснити, як працює програма, і хто ініціює повтор. Першим виконується предикат repeat, що нічого не робить, далі – стандартні предикати, що не мають альтернатив, й останнім предикат do_answer, що і забезпечує відкат після невдачі до предикату repeat за рахунок присутності в ньому предиката fail.

Завдання 3.

Задокументуйте в правилі do_answer предикат fail і запустіть програму на виконання. Зверніть увагу, що наявність у програмі предикату repeat ще не забезпечує повторів, оскільки для організації повторів необхідне повернення до предикату repeat. Зніміть коментар.

Але якщо відкат до repeat викликає do_answer, то він повинний і забезпечити, за певних умов, закінчення цього процесу. Якщо за умову виходу прийняти, наприклад, ввід слова “stop” замість прізвища, то можна до визначити предикат do_answer ще одним правилом:

do_answer(X) :- X="stop", write("good bye").

яке буде щирим при узгодженні, і яке, через відсутність ознаки невдачі, не викликає відкату до предиката repeat.

Завдання 4.

Додайте нове правило в останній рядок процедури. Запустіть програму на виконання спочатку в звичайному режимі, а потім – у режимі трасування, але тільки предикату do_answer. Переставте нове правило на перший рядок процедури і виконаєте трасування. Який вийшов результат? Що буде, якщо правило для умови виходу записати у виді:

do_answer("stop"):-write("good bye").

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

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