Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
AlgStr / Библиотека / ЛЕКЦИИ / POSIBNIK / ПРОГР НА ПРОЛОГЕ.doc
Скачиваний:
42
Добавлен:
23.03.2015
Размер:
669.7 Кб
Скачать

5.3. Метод відсікання та відкоту (вв)

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

У загальному випадку для реалізації цього методу може знадобитися застосування предиката “відсікання” (“!” або “cut”) (див. розд. 5.7). Цей предикат, обчислення якого завжди завершується успішно, змушує внутрішні уніфікаційні процедури “забути” всі покажчики відкоту, установлені під час спроб обчислити поточну підціль.

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

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

Проілюструємо даний метод для попередньої бази даних про студентів факультету, поставивши умову - друк студентів факультету до студента з прізвищем Петров включно:

друк_студентів:-

студент(Група, Студент, Стипендія),

write(Студент,” “,Стипендія), nl,

Студент = петров.

Дія цієї програми основана на тому, що відкоти будуть збуджуватися тільки доти, поки значення змінної “Студент” не буде дорівнювати “петров”. Змінимо частково постановку задачі: необхідно роздрукувати інформацію про призначення стипендії для всіх студентів на прізвище Петров. Для цього необхідно умову перевірки прізвища студента поставити перед предикатом write, а механізм відкоту збудити явно за допомогою предиката fail, без застосування відсікання:

друк_студентів:-

студент(Група, Студент, Стипендія),

Студент = петров,

write(Студент,” “,Стипендія), nl,

fail.

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

друк_студентів:-

студент(Група, Студент, Стипендія),

Студент = петров,

!,

write(Студент,” “,Стипендія), nl,nl,

змагання(Група, Студент, Вид_спорту),

write(“ “, Вид_спорту), nl,

fail.

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

змагання(“ПЗ-98-1”, іванов, баскетбол).

змагання(“ПЗ-98-1”, петров, волейбол).

змагання(“ПЗ-98-1”, петров, стрільба).

змагання(“ПЗ-99-1”, павлов, теніс).

. . .

змагання(“ПЗ-98-1”, сидоров, шахи).

Якщо застосовувати недетерміновану версію предиката “належить” (див. розд. 5.7), то предикат print_list можна реалізувати в такий спосіб:

print_list(L):-

належить(X, L),

write(X), nl,

fail.

print_list(_).

Тут предикат “належить” застосовується для генерації при відкотах різних значень елементів списку. Предикат write виводить згенеровані значення елементів списку на екран, а fail збуджує відкіт для одержання нових (альтернативних) значень елементів списку. При відкоті всі зроблені в процедурі позначення змінних анулюються, тобто змінна X стає вільною, що нам і потрібно. Результат роботи предиката write не зникає (побічний ефект), і наступного разу друкується нове значення змінної X, згенероване предикатом “належить”. Друге твердження процедури служить для того, щоб процедура print_list завжди завершувалася успішно.

Дана схема організації повторення працює тільки у випадку, коли використовується побічний ефект (вивід на екран монітора, вивід у файл або додавання до внутрішньої бази даних). Якщо для генерації ряду значень використовувати детерміновану процедуру або, наприклад, предикат “читання вхідних даних” (read), то дана програмна структура з предикатом fail працювати не буде.