- •Аннотация
- •Лабораторная работа № 1 «Логическое программирование задачи поиска пути на конечных графах пространства состояний»
- •1.1.1. Прямой поиск (от исходной вершины до целевой вершины).
- •Самостоятельная часть работы
- •1.1.2. Обратный поиск (от целевой вершины к исходной).
- •Самостоятельная часть работы.
- •Самостоятельная часть работы
- •Задание №1.3. Поиск пути в неориентированном графе.
- •Самостоятельная часть работы
- •Задание №1.4. Поиск в псевдо бинарном дереве.
- •Самостоятельная часть работы
- •Самостоятельная часть работы
- •Задание 1.6. Поиск пути в ориентированном ациклическом графе с обходом вершин «в ширину».
- •I j k
- •Самостоятельная часть работы.
- •Задание № 1.7. Программирование поиска в глубину на конечном графе пространства состояний на языке clips
- •Самостоятельная часть работы
Самостоятельная часть работы
Изобразите бинарное дерево по приведенным фактам tree.
Дополните программу lab1_4м.pro операторами write, чтобы проследить весь путь обхода графа при поиске заданной вершины; сокращается ли обход по сравнению с представлением дерева бинарными фактами?
Дополните программу для возможности вывода пути из Y в X (методом обратного поиска по аналогии с первым заданием).
Реализуйте вышеизложенную идею проверки условия, не является ли целевой правая вершина очередного поддерева, что может сделать поиск более эффективным.
Внесите изменения в программу, позволяющие исключить факты связи терминальных вершин с пустыми поддеревьями.
Задание №1.5. Ускоренный поиск в псевдо бинарном дереве с индексацией вершин.
Существенного повышения эффективности поиска можно достичь, если у каждой вершины поставить числовой ключ с таким расчётом, чтобы в левом поддереве все ключи были всегда меньше, а в правом - больше, чем в корневой вершине. В псевдо бинарном дереве это делается вручную. Рассмотрим пример индексации вершин бинарного дерева с 15-ю вершинами из предыдущего задания.
a (8)
b (4)
c (12)
d (2)
e(6)
f(10)
g(14)
m(9)
i (1)
h(3)
p(5)
n(7)
k(11)
l(13)
s(15)
Представим себе числовую ось с №№ с 1 по 15. Выберем примерную середину оси (8) и присвоим это значение корневой вершине (а). Тогда в левом поддереве номера вершин должны быть меньше 8, а в правом - больше. С каждым полученным интервалом (1-8) и (8-15) поступим аналогично, т.е. найдём примерные их середины (пусть это будут 4 и 12) и присвоим эти индексы вершинам «b» и «c» соответственно. Теперь на числовой оси стало 4 интервала. Найдём их примерные середины. Пусть это будут 2, 6, 10 и 14, и присвоим эти индексы соответственно вершинам d, e, f и g третьего уровня графа. Остальные индексы расставим у терминальных вершин соблюдая условие: индекс левого поддерева меньше, а правого – больше, чем индекс их корня. В итоге получим модель индексированного бинарного дерева (в среде VisualPrologтакие деревья строятся автоматически и называются В+ деревьями).
Полученное дерево с индексами вершин можно представить в виде совокупности фактов-предикатов tree(X, K, L, R) по аналогии с предыдущим заданием, где X-данная корневая вершина, K - её индекс, L, R- поддерживающие вершины слева и справа. Для терминальных вершин, как и в предыдущей программе, L и R-пустые поддеревья, обозначаемые как v.
Целевой предикат - wtreemember(K, X, Y), где K - индекс (ключ) искомой вершины, X-корневая вершина дерева, в котором ведётся поиск, Y- искомая вершина. Ниже приведено правило поиска заданной вершины Y с использованием индексов, а также простейшего вывода вершин на пути от X к Y (с помощью оператора write).
wtreemember(K, X, X): - tree(X, K,_,_), write(X, «;»), nl.
wtreemember(K, X, Y):-tree(X, FK, L,_), K < FK, write(X, «,»), wtreemember(K, L, Y).
wtreemember(K, X, Y):-tree(X, FK,_,R), K > FK, write(X, «,»), wtreemember(K, R, Y).
Первое предложение - условие окончания рекурсии, означающее, что мы спустились вниз по дереву до вершины, ключ которой FKсовпал с заданным значением К в цели. Тогда эта вершина Х передается в третий аргументwteememberкак найденная целевая. 2-е и 3-е предложения - рекурсивные процедуры поиска соответственно в левом и правом поддеревьях. Вначале всегда рассматривается правило для левого поддерева путём сравнения ключа поиска K с ключом FK текущего фактаtree. Если условие выполнено, происходит рекурсивный вызов правила с вершиной левого поддереваL. Это означает, что целевая вершина находится в левом поддереве. Если условие не выполнено, т.е.K>FK, переходим к третьему предложению, которое рекурсивно вызовет правило с вершиной правого поддереваR. Это значит, что цель находится в правом поддереве. Но предикатwtreemember(K,R,Y) опять будет обращаться ко второму предложению, т.е. пытаться осуществить поиск сначала в левом поддереве дерева с корнемR.
Таким путем решается задача выбора кратчайшего пути к целевой вершине, в котором находится искомый ключ. Напишите протокол поиска, задавшись, например, целью wtreemember(9,a,Y), и Вы убедитесь, что в каждой развилке программа выбирает кратчайший путь к искомой вершине с помощью сравнения ключа с индексом. В нашем примере по ключу 9 найдём вершину Х = m, значение которой будет передано в цель как искомое по ключу 9 значение Y. Это один из самых быстрых методов поиска, и он является аналогом поиска в В+ деревьях в БД наVisualProlog.