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

1.1.1. Прямой поиск (от исходной вершины до целевой вершины).

Рассмотрим ориентированный ациклический граф:

a

d

c

f

g

j

h h

i

Наличие ориентированной связи двух соседних вершин отображается в программе в виде фактов-предикатов edge(x,y).

edge(a,c). edge(c,f). edge(f,h). edge(f,i).

edge(c,g). edge(a,d). edge(d,j).

Семантика связи edgeможет быть различной и зависит от предметной области (ПО). Например, фактыedgeможно истолковать как отношение следования: из «a» следует «c». В программе эти факты будут рассматриваться последовательно по строкам. Порядок расположения фактов влияет на последовательность шагов программы, но не на результат.

Задача поиска пути допускает следующую логическую формулировку. Чтобы найти путь, например, из вершины “а” в i, необходимо вначале решить более простую задачу: найти одну из вершин, с которой непосредственно связана “а”, а затем искать путь от этой вершины к цели, пользуясь тем же самым правилом. Задача решается рекурсивно. Цель при этом редуцируется (понижается). Разворачивание рекурсии идет до тех пор, пока очередная исходная вершина не совпадет с целевой. Такое программирование, когда дана цель и правила поиска (но не алгоритм!) называется декларативным, недетерминированным (поскольку в некоторых вершинах имеются варианты выбора продолжения пути), свойственным задачам искусственного интеллекта.

path(X,X,[X]).

path(X,Y,[X|P]):-edge(X,N),path(N,Y,P).

Первая переменная (аргумент) предиката path- заданная исходная вершина, второй аргумент - целевая вершина, третий аргумент - искомый список вершин пути. Первое предложение представляет собой условие окончания рекурсии. Его декларативный смысл: существует (истинен) путь из вершины X в неё же саму, представляющий собой список из самой вершины [X]. Второе предложение декларирует: путь из вершины X в вершину Y представляет собой список [X|P] (с головным элементом Х в виде текущей вершины), если существует реброedgeот вершины X до соседней вершины N и поставлена рекурсивно цель: найти путь P из вершины N в вершину Y. Обратите внимание, что Р является хвостом искомого списка головы правила (обозначаются одинаковым символом).

Напомним, что Пролог будет пытаться поочередно применить оба предложения правила path в порядке их расположения, отыскивая соответствующие значения переменных. При этом переменные и атомы (константы) из начальной цели, а затем из текущих целей всегда подставляются вместо переменных в голову проверяемого правила.Для лучшего понимания работы более сложных логических программ следует научиться составлять протокол прямого и обратного хода (шагов выполнения программы поиска). Протокол состоит из последовательных вызовов правил с новыми значениями переменных. Переменныепереименовываются, чтобы отобразить, что на каждом шаге рекурсии используемое правило целиком загружается в стек со своими значениями переменных. Следует напомнить, что притрассировкенеозначенные переменные на прямом ходе показываются как анонимные (символом подчеркивания), что затрудняет понимание работы программы в отличие от протокола с именованными переменными. Протокол в особенности полезен при наблюдении за присвоением значений на обратном ходе рекурсии, когда формируется ответ.

Протокол работы вышеприведенной программы с целью path(a,i,Path)

(Определение. Цель – это любой предикат, у которого хотя бы один аргумент является переменной).

Цель вначале сопоставляется с первым предложением вышеприведенного правила, но она ему не подходит, поскольку в этом предложении правила два первых аргумента должны быть одинаковы, а в цели они разные. Подставляем переменную Pathи атомы а,iиз целив головувторого предложения:

path(a, i, Path):-edge(a, N), path(N, i, P).

Но в голове, согласно правилу, переменная Pathдолжна быть списком [X|P], где Х=a. Поэтому в протоколе надо написать:

path(a, i, [a|P] ):-edge(a, N), path(N, i, P). %Pathзаменяем на [a|P].

В теле получаем две подцели с переменными NиP. Сопоставление первой подцели edge(a, N) с первым подходящим фактом edge(a,c) даёт унификацию N = c. Другие подходящие факты интерпретатор отмечет указателями для возможности поиска с возвратом. Следующий предикат порождает новую подцель path(c,i,P), переменная и атомы из которой должны подставляться в правило. Для этой цели подходящим опять оказывается второе предложение:

path(c, i, [c|P1]): - edge(c, N), path(N, i, P1).

Но здесь P = [c|P1], и мы вынуждены в протоколе ввести в качестве хвоста новую переменную P1, так как спискиPиP1 находятся теперь на разных “этажах” стека и отличаются друг от друга на элемент “а”. Обращение к фактамedgeдаёт N = f, и второй предикат формирует новую цель:

path(f, i, [f|P2]): - edge(f, N), path(N, i, P2).

Здесь Р1 заменяется на [f|P2] по той же причине, что и в предыдущем случае, и мы вынуждены ввести переменную P2. Из сопоставления с фактамиedgeнаходим N = h, и новая цель будет:

path(h, i, [h|P3]): - edge(h, N), path(N, i, P3)

Но в БД отсутствует факт edge с первым аргументом h, и цель edge, а вместе с ней всё предложение терпит неудачу. Интерпретатор Пролога осуществляет возврат по указателю к предыдущему шагу рекурсии, отменяет последнюю унификацию N = h, и находит другой факт связи для вершины f: edge(f, i), отсюда следует, что N = i, и новая цель:

path((i,i,P2) % Возвращаемся к переменной Р2 из предыдущего шага.

Эта цель успешно разрешается путем сопоставления с первым предложением правила path:

path(X,X,[X]) при унификации X=i, откуда [X] = P2 = [i].

На этом заканчивается прямой ход рекурсии и далее происходит присваивание в обратном порядке значений переменным P1, P и Path, находящимся в правилах, помещенных ранее на разных “этажах” стека:

Т.к. P2 = [i], то P1 = [f|P2] = [f, i], P = [c|P1] = [c, f, i], Path = [a|P] = [a, c, f, i]

Цель достигнута: переменная Pathполучила значение списка пути [a,c,f,i]. Как видно из протокола, фактический путь поиска был [a,c,f,h,f,i] и представлял собой участок обхода дерева от корня в глубину. В ответе неуспешный ход [h,f] опускается.

Рассмотренный пример является прямым поиском от X к Y, который задаётся тем, что переменная Nв предикате edge является вторым аргументом, а в вызывающем предикате path(N,Y,P) - первым. Это означает, что при сворачивании рекурсии, т.е. при работе правила “справа налево”, к хвосту (а вначале это целевая вершина) будут добавляться в обратном порядке пройденные головные вершины пути. В итоге список пути окажется прямым и будет находиться в голове правила, откуда он и передается в цель path(a,i,Path) для получения ответа о значении переменнойPath.

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