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

5.18.6 Поиск в ширину

Здесь будем представлять множества списком путей кандидатов, а каждый путь - списком вершин в обратном порядке, т.е. головой списка будет самая последняя вершина, а последним элементом списка - стартовая вершина.

a

b c d e

Особенность :

В списке ОТК будем хранить не имена пройденных нами вершин, а пути-кандидаты.

1. [ [a] ] Дерево

2. [ [b,a], [c,a] ] a

3. [ [c,a], [d,b,a], [c,b,a] ] / \

4. [ [d,b,a], [c,b,a], [f,c,a], [g,c,a] ] b c

5. [ [f,c,a], [g,c,a] ] /\ /\

d e f g

целевая

Алгоритм поиска в ширину состоит из следующих пунктов:

1. Поместить в список путей-кандидатов исходную вершину.

2. Является ли 1-ая вершина 1-го пути-кандидата целевой?

Если "да", то - выдать путь-кандидат.

3. Иначе - удалить 1-ый путь-кандидат из последователь-

ности путей-кандидатов, найти его продолжения и доба-

вить их в конец последовательности путей-кандидатов.

4. Go to 2.

Существует такой предикат : bagof(X,P,L) - собирает все объекты X, удовлетворяющие условию P, в список L.

Этим предикатом мы будем пользоваться для того, чтобы получить список продолжений некоторого пути-кандидата.

solve(Start,R) :- width_sch( [[Start]], R).

width_sch( [[B|W]|_], [B,W] ):- goal(B).

width_sch( [[B|W]|Ways],R ):-

 _bagof( . [B1,[B|W]],

( after(B,B1),not element(B1,[B|W]) ),

New_W  _) .,

%

% После выполнения bagof() получим: [ [b,a], [c,a] ]

%

concat(Ways, New_W, Ways_1),

width_sch(Ways_1, R),

width_sch(Ways, R).

%

% Этот (последний) вызов предиката width_sch() связан с

% отбрасыванием тупиковых ветвей, когда after(B,B1)=false

%

 findall и  setof  - выполняют работу, подобную bagof().

Поиск с использованием алгоритма равных цен м.б. реализован на базе  программы.

Только сейчас: Все новые пути-кандидаты - помещаются в

конец списка.

надо : После получения списка Ways_1 отсортировать

его.

Рассмотренный алгоритм поиска в ширину связан со списко-

вым представлением дерева поиска, что не эффективно поскольку

начальные участки путей могут многократно повторяться. Поэтому

рассмотрим древовидное представление данных, что улучшит рабо-

ту программы поиска в ширину.

Здесь речь не пойдет о бинарном дереве : a

/ \

1 2 , нет,

под деревом будем понимать запись, вида:

T(B,SubT) <==> Д(Верш,Пд) - где

В - вершина,

SubT - список поддеревьев

SubT ::= { Пд1, Пд2, ... ,ПдN }

Кроме того - если имеется вершина В и она является узлом, то дерево с такой вершиной будем называть "листом" и обозначать L(B).

Например a описывается с учетом введенных обозначе-

/ \ ний следующим образом :

b c

/ \ / \ T( a,[ T( b,[ L(d), L(e)] ),

d e f d T( c,[ L(f), L(d)] ), ] )

такая структура дерева более эконо-

мит память.

Введем предикат:

 let_width(W, T, T1, ExS, S). или

расширить(П, Д, Д1, СщР, Р) - где ( см. рис.* )

П (путь)/W (way) - путь, ведущий из старто-

вой вершины в корень де-

рева Д/T ,

Д (дерево)/T (tree) - путь до промежуточной

вершины ,

Д1(дерево1)/T1(tree1) - расширение дерева Д/Т

на один уровень ,

Р (решение)/S (solving) - путь, продолженный

до целевой вершины.

СщР (существует решение)/ExS (exist solving)

W

T

T1

Рис. *.

В этом предикате переменные W и T должны быть всегда определены (конкретизированы).

Идея алгоритма состоит в следующем:

Нужно расширять дерево T до тех пор, пока в ходе расширения не встретится целевая вершина.

Предикат let_width(W, T, T1, ExS, S) будет порождать 2 вида решений, зависящих от значения переменной ExS :

1. ExS = "да" ==> S - конкретизировано

Т1 - не конкретизировано

2. ExS = "нет" ==> S - не конкретизировано

Т1 - конкретизировано

Определим предикат solve()

с использованием предиката let_width()

Идея алгоритма - в каждый текущий момент расширяется дерево. Если в процессе расширения встретится целевая вершина, то необходимо выдать решающий путь, являющийся продолжением пути W от текущей корневой вершины до целевой вершины G.

solve( Start, Solving ):- width_sch( L(Start), Solving).

width_sch( T, S):-

let_width([], T, T1, ExS, S),

( ExS = да;

ExS = нет, !, width_sch(T1,S) ).

let_width( W, L(B), _, да, [B|W] ) :- goal(B).

let_width( W, L(B), T(B,SubT), нет, _) :-

bagof( L(B),

( after(B,B1), not element(B1,W) ),

SubT ).

let_width( W, T(B,SubT), T(B,SubT1), ExS, S) :-

let_width_all([B|W], SubT, SubT1, ExS, S).

% -------------------------------------------------------

% Предикат  _let_width_all() . (расширить_все) расширяет все

% деревья из списка под-деревьев (Пд), выбрасывает все

% тупиковые ветки и собирает все полученные расширения в

% список Пд1.

% Определим его:

% Список Пд представляется в виде головы и хвоста, затем

% с помощью let_width() расширяется голова списка Пд,

% проверяется значение переменной ExS - существует ли ре-

% шение в ходе расширения. Если решение существует, то

% ExS=да, иначе ExS=нет. Если ExS=нет, то расширяется

% хвост списка Пд с помощью let_width_all()

% -------------------------------------------------------

%

let_width_all(W, [T|TT], [TT1], ExS, S):-

let_width(W, T, T1, ExS1, S),

( ExS1 = да, ExS = да;

ExS1 = нет, !,

let_width_all(W, TT, [T1|TT1], ExS, S) ).

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]