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

5.11. Комбінація спадних і висхідних рекурсивных обчислень (ксвро)

Задача. Скласти процедуру, що виконує вирівнювання списку з підсписками (вирівнювання списку полягає в виведенні всіх елементів вихідного списку на один рівень):

вирівнювання(вихідний_список, вирівняний_список)

Ціль: вирівнювання([2, [1, 3], [4]], F).

F = [2, 1, 3, 4].

Ціль: вирівнювання([[2, 4], [ ], [1], 3], F).

F = [2, 4, [ ], 1, 3].

Передамо всю роботу по вирівнюванню вихідного списку допоміжній процедурі приховане_вирівнювання (використовує висхідну рекурсію):

вирівнювання(L, F):-

приховане_вирівнювання(L, [ ], F).

Процедуру приховане_вирівнювання будемо розробляти методом аналізу станів.

Етапи:

1. Вигляділення трьох станів:

а) вихідний список – порожній;

б) вихідний список – непорожній, і головою вихідного списку також постає список;

в) вихідний список – непорожній і головою списку постає деякий елемент –не список.

2. Розпізнання станів за допомогою аргументів, що мають такий вигляд:

а) [ ];

б) [ [H | T] | L];

в) [H | T].

3. Реалізація поводження процедури в цих станах у такий спосіб:

а) фактом

приховане_вирівнювання([ ], [ ]).

% Якщо перший список порожній, то й результатом буде

% порожній список

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

приховане_вирівнювання([ [H | T] | L], S, F):-

приховане_вирівнювання(L, S, Вирівн),

приховане_вирівнювання([H | T], Вирівн, F).

% Додатковий аргумент S дає список, вирівняний до

% даного моменту. При першому виклику – це порожній

% список. Перша підціль тіла правила дає список Вирівн, що

% містить елементи вирівняного списку L, поміщені в початок

% списку S. Друга підціль, використовуючи список Вирівн як

% вхідний, дописує до нього на початок результат

% вирівнювання списку [H | T], одержуючи результуючий

% список F.

в) У третьому стані об'єкт H буде додан у голову вихідного списка, а хвіст вихідного списку буде будуватися за допомогою рекурсивного виклику (спадна рекурсія з прогресуючою підстановкою):

приховане_вирівнювання([H | T], S, [H | L]):-

приховане_вирівнювання(T, S, L).

4. Розташування тверджень у такому ж порядку. Одержимо:

вирівнювання (L, F):-

приховане_вирівнювання(L, [ ], F).

приховане_вирівнювання([ ], [ ]).

приховане_вирівнювання([[H | T] | L], S, F):-

приховане_вирівнювання(L, S, Вирівн),

приховане_вирівнювання([H | T], Вирівн,F).

приховане_вирівнювання([H | T], S, [H | L]):-

приховане_вирівнювання(T, S, L).

Проілюструємо поводження цієї процедури на прикладі вирівнювання списку [[2, 4], [ ], [1], 3] (рис. 20).

Ціль: вирівнювання([[2, 4], [ ], [1], 3], F).

Вхідний список [[2, 4], [ ], [1], 3]

(перший аргумент)

Допоміжний список: [ ] Вхід Результуючий список [2, 4, [ ], 1, 3]

(другий аргумент)

[ ] Вихід

(Третій аргумент

2 у базовому стані )

[ ]

4

1 [ ] 3 [ ]

Рис. 20. Вирівнювання списку з підсписками

Вирівнювання цього списку можна подати у вигляді обходу дерева:

[ ] - позначає вершину, у якій досягається базовий стан;

- позначає вершину, у якій досягається другий стан (перший елемент списку являє собою список);

- позначає вершину, у якій досягається третій стан (перший елемент списку не є список).

Дана процедура обходить дерево у зворотному порядку, тобто за формулою П-Л-К (Праве – Ліве – Корінь). Якщо ліва і права гілки, що ростуть із вершини, самі – дерева, тоді першим обходиться праве піддерево (стан 2). Якщо ліва гілка – лист, то вона формує частину вихідного списку, що знаходиться в голові того списку, який формується при обході правого піддерева (стан 3).

На жаль, хоча дана процедура й повертає правильний результат

Ціль: вирівнювання([[2, 4], [ ], [1], 3], F).

F = [2, 4, [ ], 1, 3]

при активізації відкоту, вона буде видавати й неправильні альтернативні відповіді:

F = [2, 4, [ ], [1], 3]

F = [[2, 4], [ ], 1, 3]

F = [[2, 4], [ ], [1], 3]

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

Перший стан ніяких питань не викликає: він є винятковим стосовно другого і третього. Але список, форма якого [H | T] не виключає і списку з формою [ [H | T] | L]. Іншими словами, список, узгоджений зі зразком [ [H | T] | L], буде узгоджений і зі списком [H | T]. Нам необхідний якийсь механізм, що не допускав би того, щоб у третьому стані змінна H відповідала непорожньому списку. Це можна реалізувати за допомогою сторожової цілі

H <> [ _ | _ ]

доданої до твердження для третього стана.

От тепер ми одержимо кінцевий результат нашої задачі:

вирівнювання (L, F):-

приховане_вирівнювання(L, [ ], F).

приховане_вирівнювання([ ], [ ]).

приховане_вирівнювання([ [H | T] | L], S, F):-

приховане_вирівнювання(L, S, Сглаж),

приховане_вирівнювання([H | T], Сглаж, F).

приховане_вирівнювання([H | T], S, [H | L]):-

H <> [ _ | _ ],

приховане_вирівнювання(T, S, L).

Можна забезпечити винятковість другого й третього стану процедури за допомогою відсікання. Це даст такий варіант реалізації процедури “вирівнювання”:

вирівнювання (L, F):-

приховане_вирівнювання(L, [ ], F).

приховане_вирівнювання([ ], [ ]).

приховане_вирівнювання([[H | T] | L], S, F):-!,

% це відсікання постачає третє твердження неявною сторожовою

% ціллю

приховане_вирівнювання(L, S, Вирівн),

приховане_вирівнювання([H | T], Вирівн, F).

приховане_вирівнювання([H | T], S, [H | L]):-

% H <> [_|_], - тепер ця сторожова ціль непотрібна

приховане_вирівнювання(T, S, L).