Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
lab1_1hse.doc
Скачиваний:
8
Добавлен:
08.02.2015
Размер:
102.5 Кб
Скачать

Самостоятельная часть работы

  • Объясните на примере протокол работы программы.

  • Задайте цель в виде запроса tree(X,9,_,_). Запустите программу в режиме трассировки, чтобы посчитать число последовательных сопоставлений со списком фактов, которое потребовалось программе для ответа.

Задание 1.6. Поиск пути в ориентированном ациклическом графе с обходом вершин «в ширину».

Применяемый метод поиска является прямым, но перебор вершин происходит в ширину. Особенность рассматриваемой ниже программы SEARCH состоит в том, что при поиске заданной конечной вершины среди вершин текущего уровня графа одновременно формируются и сохраняются в стеке списки путей откаждой из нихкобщей начальной. Эти списки представлены в инверсном виде: в голове каждого списка пути стоит одна из вершин текущего уровня графа, а в конце общая начальная. Поэтому при совпадении головы одного из списков с целевой вершиной не требуется дополнительной процедуры поиска пути, он будет содержаться в головном элементе списка списков всех путей. Но для хранения всех списков путей требуется большая память стека.

Рассмотрим пока без программы, как происходит процесс генерации новых путей и поиск заданной конечной вершины (см. рис.ниже).

Вначале рассматривается единственная вершина 1-го уровня - исходная. Это вершина «а». С помощью фактов edge(x,y) определяются все вершины, связанные с «a», в данном случае это «b», «c» и «d», и формируются инверсные списки пути от этих вершинв «a»: [b,a], [c,a], [d,a]. Все пути собираются в общий список списков: [[b,a], [c,a], [d,a]]. Далее идет поиск целевой вершины в головном списке списков. При этом отделяется головной список [b,a],

a

b

d

c

e

f

g

h

I j k

l

n

r

m

o

p

q

s

t

u

v

а в нем в свою очередь отделяется головной элемент, в данном случае «b», и сравнивается с заданной целевой вершиной:

[[b|a]|[c,a],[d,a]]

Если совпадение произошло, то выводится искомый путь: [b,a]. Если же совпадения не произошло, то по фактам edge определяются продолжения путей от «b» на следующий уровень графа. Это вершина «e». Она добавляется в голову неуспешного списка [b,a] и получаем новый инверсный путь от вершины «e» к «a», т.е. список [e,b,a], который заменяет собой предыдущий [b,a], так как вершина «b» не целевая, и ставится в конец обновленного списка списков путей, который образуется путем объединения хвоста 1-го списка списков, т.е. [[c,a],[d,a]], с новым путем [e,b,a], который ставится в конец. Получается новый список путей:

[[c,a],[d,a],[e,b,a]]

На первое место в этом списке вышла следующая вершина рассматриваемого уровня графа «c». Применим то же правило, отделив головной список, а в нем головной элемент:

[[c|a]|[d,a],[e,b,a]]

Допустим, головной элемент «c» опять не совпадает с заданной целевой вершиной. Тогда от «c» следует образовать продолжения путей на следующий уровень графа. По фактам edge вершина «c» связана с «f» и «g». В этом случае порождаются два новых инверсных пути [f,c,a] и [g,c,a]. Они заменяют собой путь [c,a] и ставятся в конец нового списка списков, который образуется путем объединения хвоста предыдущего списка, т.е. [[d,a][e,b,a]], с новыми путями [f,c,a] и [g,c,a]. Получим список списков:

[[d,a],[e,b,a],[f,c,a],[g,c,a]]

Теперь, как видим, на первое место выходит элемент «d» - последний в списке вершин 2-го уровня, образованном от «a». Следующими будут рассмотрены вершины «e», «f», «g» , т.е. вершины 3-го уровня. Такой процесс продолжится, пока в голове одного из списков не обнаружится конечная вершина пути. Этот список и будет искомым путём. В противном случае появится сообщение, что пути нет.

Рассмотрим программную реализацию изложенного алгоритма. Правило верхнего уровня:

search(BN, EN, Result): - widesearch ([[BN]], EN, Result).

Первые два аргумента целевого предиката search являются задаваемыми начальной (BN) и конечной (EN) вершинами искомого пути. Третий аргумент Result - возвращаемый список вершин искомого пути (если, конечно, таковой имеется).

Первый аргумент предиката widesearch - список инверсных путей от всех текущих, еще не рассмотренных на предмет совпадения с целью, вершин данного уровня графа к исходной вершине. Этот аргумент описан как список списков. Остальные аргументы имеют тот же смысл что и в search. При первом вызове widesearch рассмотренного правила первый аргумент состоит только из исходной вершины BN.

Основное правило поиска состоит из 2-х предложений:

widesearch([[Node|Path]|_], EN, [Node|Path]: - Node = EN,!.

widesearch([[Node|Path]|Paths], EN, Result):-findall(X,nextpath(Node, Path, X),NextPaths),

append(Paths, NextPaths, NewPaths),!, widesearch(NewPaths, EN, Result).

Первое предложение служит для опознавания одного из путей [Node|Path], стоящего в голове списка списков, как искомого, если голова Node этого пути совпадет с заданной конечной вершиной EN. В этом случае он как третий аргумент предиката widesearchбудет передан переменнойResaultзапроса. Поиск успешен.

Если совпадения Node и EN не произошло, подключается 2-ое предложение widesearch, которое выполняет всю основную работу по формированию новых путей от вершины “а” на следующий уровень. Вначале предикат findall вызывает правило nextpath:

nextpath(Node, Path, [NextNode, Node|Path]): - edge(Node, NextNode).

Это правило добавляет в голову списка Node|Path = [а] одну вершину следующего уровня [NextNode,Node|Path], определяя ее с помощью факта edge. В вызывающий предикат nextpath правила findall этот новый путь [NextNode,Node|Path] возвращается на место свободной переменной X. В рассмотренном выше примере это будет список [b,a]. Затем предикат findall повторяет вызов правила nextpath для поиска других возможных продолжений отNodeвниз на следующий уровень, т.е. с иd, и собирает полученные списки в своем третьем аргументе NextPaths. В нашем примере переменнаяNextPathsполучит значение [[b,a], [c,a], [d,a]]. Следующий предикат append вызывает правило объединения двух списков в третий, выходной список. Аргументы append должны быть описаны как списки списков. Первый аргумент — хвост предыдущего списка путейPaths, в нашем случае он пока пустой, второй — новые пути NextPaths, третий — результат их объединения в список NewPaths, т.е. вNewPathsполучим список [[b,a], [c,a], [d,a]]. Этот список списков передается последнему предикату widesearch в качестве 1-го аргумента и происходит рекурсивный вызов правила widrsearch. Первое предложение этого правила опять проверит выполнимость условия окончания поиска по совпадениюголовного элемента головного списка, в данном случае, bс заданной конечной EN. Если совпадения не произошло, то второе предложение widesearch будет искать продолжения пути от неуспешной вершиныbна следующий уровень в том же порядке, какой был описан выше.

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