Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Метод_Пролог_Етап2_3.doc
Скачиваний:
14
Добавлен:
14.11.2019
Размер:
1.46 Mб
Скачать

Реалізація деяких методів пошуку в просторі станів на Пролозі.

Простір станів на Пролозі можна представити у вигляді відношення after(x, y). Наприклад, якщо простір станів зображується у вигляді такого дерева:

Рис.8.

то його записують таким чином:

after(a,b).

after(b,c).

after(a,d).

after(d,e).

Пошук у глибину реалізується на Пролозі за допомогою наступної ідеї:

Для того, щоб знайти шлях Solution із даної вершини A в деякі цільову вершину, необхідно:

  • якщо A – це цільова вершина, то установити Solution = A, або

  • якщо для вихідної вершини A існує вершина спадкоємець A1, така, що можна провести шлях Solution1 із A1 в цільову вершину, то установити Solution = [A | Solution1].

На Пролозі це правило записується так:

solve(A, [A]) :-

destination(A).

solve(A, [A|Solution]) :-

after(A, A1),

solve(A1, Solution).

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

Пошук в ширину програмується важче, ніж пошук в глибину, тому що доводиться зберігати всю множину вершин-кандидатів, а не тільки одну. Крім того, якщо нам треба отримати розв’язувальний шлях, то однієї множини вершин не достатньо. Тому будемо зберігати не множину вершин-кандидатів, а множину шляхів-кандидатів. Простір станів у цьому випадку зручно представляти за допомогою відношення children(x, [y, z]). Наприклад, дерево

Рис.9.

записується таким чином:

children(a, [b, e]).

children(b, [c, d]).

children(e, [f]).

Будемо шукати відношення пошуку в ширину breadth_star(Roads, Answer). Це відношення буде істинним, якщо існує шлях із множини кандидатів Roads, який може бути продовжено до цільової вершини. Цей продовжений шлях і є Answer.

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

Загальні принципи пошуку в ширину такі:

Для того, щоб виконати пошук в ширину при заданній множині шляхів-кандидатів, необхідно:

  • якщо голова першого шляху – це цільова вершина, то взяти цей шлях як розв’язок, інакше

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

Наступна програма реалізує цей алгоритм:

breadth_first(Start,Answer):-

breadth_star( [[Start]], Answer).

breadth_star( [[H|Road]|_], [H|Road] ):-

destination(H).

breadth_star( [[H|T]|Roads], Answer ) :-

children(H, Children), make_road(Children, [H|T], Child_Roads),

append1( Roads, Child_Roads, New_Roads ),!,

breadth_star( New_Roads, Answer ).

breadth_star(Roads, Answer). % випадок, якщо у Н немає спадкоємця

Множина продовжень шляху породжується двома відношеннями children(H, Children) і make_road(Children, [H|T], Child_Roads), перше відношення спочатку породжує список вершин-спадкоємців Children вершини H, а друге – список шляхів-спадкоємців Child_Roads, які ведуть із вершини H. Предикат make_road можна реалізувати так:

make_road([], _, []).

make_road([H|T], L, [New_L|T1]):-

append([H], L, New_L),

make_road(T, L,T1).

Предикат append1( Roads, Child_Roads, New_Roads ) додає множину шляхів-продовжень в кінець множини шляхів-кандидатів:

append1([],L,L).

append1([X|L1],L2,[X|L3]):-

append1(L1,L2,L3).

Якщо у вершини H немає вершин-спадкоємців і відношення children(H, Children) отримує невдачу забезпечується альтернативний запуск процедури breadth_star(Roads, Answer).