e45c7a9fc4f7e11bb97d6f5df39ced5f.ppt
- Количество слайдов: 35
Сошников Дмитрий Валерьевич к. ф. -м. н. , доцент dmitryso@microsoft. com Логическое программирование Факультет Прикладной математики и физики Кафедра Вычислительной математики и программирования Московский авиационный институт (государственный технический университет)
1 4 2 3 5 6 7 © 2009 Сошников Д. В. Игра в 8 8 : - pred final(probstate: : out) is det. final([[1, 2, 3], [4, 0, 5], [6, 7, 8]]). : - pred init(probstate: : out) is det. init([[1, 3, 5], [4, 2, 8], [6, 7, 0]]). : - type row == list(int). : - type probstate == list(row). 2
© 2009 Сошников Д. В. Игра в 8 - 2 : - pred move(probstate: : in, probstate: : out) is nondet. move(A, B) : - move_lr(A, B). move(A, B) : - move_ud(A, B). : - pred move_z(row: : in, row: : out) is nondet. move_z([0, X|T], [X, 0|T]). move_z([X, 0|T], [0, X|T]). move_z([X|T], [X|R]): -move_z(T, R). : - pred move_lr(probstate: : in, probstate: : out) is nondet. move_lr([A|T], [B|T]) : - move_z(A, B). move_lr([A|T], [A|R]) : - move_lr(T, R). : - pred move_h(row: : in, row: : out, row: : out) is nondet. move_h([0|T], [A|R], [A|T], [0|R]). move_h([A|T], [0|R], [0|T], [A|R]). move_h([X|T], [Y|R], [X|T 1], [Y|R 1]) : - move_h(T, R, T 1, R 1). : - pred move_ud(probstate: : in, probstate: : out) is nondet. move_ud([A, B, C], [A 1, B 1, C]) : - move_h(A, B, A 1, B 1). move_ud([A, B, C], [A, B 1, C 1]) : - move_h(B, C, B 1, C 1). 3
© 2009 Сошников Д. В. Мораль Алгоритмы поиска (в особенности поиск в глубину) эффективно реализуются на языках логического программирования Базовые алгоритмы поиска обладают взаимоисключающими достоинствами и недостатками Алгоритм поиска с заглублением сочетает в себе достоинства обоих методов, хотя и производит исключительно много ненужных вычислений Чтобы решать реальные задачи, нужно иметь методы поиска, использующие знания о направлении поиска. 4
© 2009 Сошников Д. В. Алгоритмы поиска в нагруженных графах 5
© 2009 Сошников Д. В. Граф дорог между городами road(a, d, 4). road(a, f, 2). road(b, c, 4). road(b, d, 4). road(c, i, 4). road(d, e, 3). road(e, i, 3). road(f, g, 2). road(g, h, 2). road(h, i, 3). move(A, B, N) : - road(A, B, N); road(B, A, N). 6
Нагруженным графом (направленным) называется пара , где U — множество вершин, V U×U×R — множество дуг. Длиной пути {xi}i=0 n в нагруженном графе G= называется величина L= li, где
© 2009 Сошников Д. В. Представление пути в нагруженном графе Для поиска кратчайшего пути надо уметь сравнивать пути по длине 2 способа: Хранить длину пути вместе с путём L=3: [a, b, c] Каждый раз вычислять длину предикатом ln(L) prolong(C: [X|T], C 1: [Y, X|T]): move(X, Y, A), not(member(Y, [X|T])), C 1 is C+A. ln(C: _, C). ln([_], 0). ln([A, B|T], C) : move(A, B, C 1), ln([B|T], C 2), C is C 1+C 2. 8
© 2009 Сошников Д. В. Поиск с весовой функцией (Unified Cost Search, UCS) Наиболее очевидное решение – в «стандартном» алгоритме поиска (в ширину) продлевать в первую очередь кратчайшие в смысле весовой функции пути. Эквивалентный подход – поддерживать очередь путей в отсортированном состоянии (очередь с приоритетами). path(X, Y, P): - bdth([[X]], Y, P). bdth([[X|T]|_], X, [X|T]). bdth([P|QI], X, R) : findall(Z, prolong(P, Z), T), append(QI, T, QO), !, bdth(QO, X, R). bdth([_|T], Y, L) : - bdth(T, Y, L). 9
© 2009 Сошников Д. В. Поиск с весовой функцией - реализация path_bst(Start, Finish, Res): - bst([0: [Start]], Finish, _: Res). bst([C: [Finish|T]|_], Finish, C: [Finish|T]). bst([Path|Rest], Finish, R) : - findall(Z, prolong(Path, Z), New. Pathes), place(New. Pathes, Rest, New. Queue), !, bst(New. Queue, Finish, R). bst([P|T], F, R) : - bst(T, F, R). 10
© 2009 Сошников Д. В. Вставка в очередь place([], L, L). place([X|T], L, R) : - insert(X, L, L 1), place(T, L 1, R). insert(C: P, [C 1: P 1|R], [C: P, C 1: P 1|R]) : - C
| ? - search_bst(a, i, R). 2 -->[2: [f, a], 4: [d, a]] 2 -->[4: [d, a], 4: [g, f, a]] 3 -->[4: [g, f, a], 7: [e, d, a], 8: [b, d, a]] 3 -->[6: [h, g, f, a], 7: [e, d, a], 8: [b, d, a]] 3 -->[7: [e, d, a], 8: [b, d, a], 9: [i, h, g, f, a]] 3 -->[8: [b, d, a], 9: [i, h, g, f, a], 10: [i, e, d, a]] 3 -->[9: [i, h, g, f, a], 10: [i, e, d, a], 12: [c, b, d, a]] R = [i, h, g, f, a] ? ; 4 -->[10: [i, e, d, a], 12: [c, b, d, a], 12: [e, i, h, g, f, a], 13: [c, i, h, g, f, a]] R = [i, e, d, a] ? ; 5 -->[12: [c, b, d, a], 12: [e, i, h, g, f, a], 13: [c, i, h, g, f, a], 13: [h, i, e, d, a], 14: [c, i, e, d, a]] 5 -->[12: [e, i, h, g, f, a], 13: [c, i, h, g, f, a], 13: [h, i, e, d, a], 14: [c, i, e, d, a], 16: [i, c, b, d, a]] 5 -->[13: [c, i, h, g, f, a], 13: [h, i, e, d, a], 14: [c, i, e, d, a], 15: [d, e, i, h, g, f, a], 16: [i, c, b, d, a]] 5 -->[13: [h, i, e, d, a], 14: [c, i, e, d, a], 15: [d, e, i, h, g, f, a], 16: [i, c, b, d, a], 17: [b, c, i, h, g, f, a]] 5 -->[14: [c, i, e, d, a], 15: [d, e, i, h, g, f, a], 15: [g, h, i, e, d, a], 16: [i, c, b, d, a], 17: [b, c, i, h, g, f, a]] 5 -->[15: [d, e, i, h, g, f, a], 15: [g, h, i, e, d, a], 16: [i, c, b, d, a], 17: [b, c, i, h, g, f, a], 18: [b, c, i, e, d, a]] 5 -->[15: [g, h, i, e, d, a], 16: [i, c, b, d, a], 17: [b, c, i, h, g, f, a], 18: [b, c, i, e, d, a], 19: [b, d, e, i, h, g, f, a]] 5 -->[16: [i, c, b, d, a], 17: [b, c, i, h, g, f, a], 17: [f, g, h, i, e, d, a], 18: [b, c, i, e, d, a], 19: [b, d, e, i, h, g, f, a]] R = [i, c, b, d, a] ? ; 6 -->[17: [b, c, i, h, g, f, a], 17: [f, g, h, i, e, d, a], 18: [b, c, i, e, d, a], 19: [b, d, e, i, h, g, f, a], 19: [e, i, c, b, d, a], 19: [h, i, c, b, d, a]] …. 2 -->[23: [f, g, h, i, c, b, d, a], 24: [e, d, b, c, i, h, g, f, a]] 1 -->[24: [e, d, b, c, i, h, g, f, a]] 0 -->[] © 2009 Сошников Д. В. Порядок просмотра путей 12
© 2009 Сошников Д. В. Проблема В рассмотренных алгоритмах поиска движение происходит в направлении кратчайшего пути, но не по направлению к цели Аналогично поиску пути в городе без компаса Для повышения эффективности поиска надо иметь возможность как-то задать направление поиска Такие методы поиска называются информированными 13
© 2009 Сошников Д. В. Граф дорог с заданным направлением h(a, 10). h(b, 7). h(c, 4). h(d, 5). h(e, 3). h(f, 8). h(g, 6). h(h, 3). h(i, 0). В данном примере функция h/2 задается для фиксированной конечной вершины. Для универсального алгоритма поиска надо задавать функцию h как функцию текущей и конечной вершин. 14
© 2009 Сошников Д. В. Жадный алгоритм поиска Будем продлевать первым путь, ближайший к цели с точки зрения эвристики wt([P|_], C) : - h(P, C). place([], L, L). place([X|T], L, R) : - insert(X, L, L 1), place(T, L 1, R). insert(P, [P 1|R], [P, P 1|R]) : - wt(P, C), wt(P 1, C 1), C
| ? - search_grd(a, i, R). 2 -->[[d, a], [f, a]] 3 -->[[e, d, a], [b, d, a], [f, a]] 3 -->[[i, e, d, a], [b, d, a], [f, a]] R = [i, e, d, a] ? ; 4 -->[[h, i, e, d, a], [c, i, e, d, a], [b, d, a], [f, a]] 4 -->[[c, i, e, d, a], [b, d, a], [g, h, i, e, d, a], [f, a]] 4 -->[[b, d, a], [g, h, i, e, d, a], [b, c, i, e, d, a], [f, a]] 4 -->[[c, b, d, a], [g, h, i, e, d, a], [b, c, i, e, d, a], [f, a]] 4 -->[[i, c, b, d, a], [g, h, i, e, d, a], [b, c, i, e, d, a], [f, a]] R = [i, c, b, d, a] ? ; 5 -->[[e, i, c, b, d, a], [h, i, c, b, d, a], [g, h, i, e, d, a], [b, c, i, e, d, a], [f, a]] 4 -->[[g, h, i, e, d, a], [b, c, i, e, d, a], [g, h, i, c, b, d, a], [f, a]] 4 -->[[b, c, i, e, d, a], [g, h, i, c, b, d, a], [f, g, h, i, e, d, a]] 3 -->[[f, a], [f, g, h, i, e, d, a], [f, g, h, i, c, b, d, a]] 3 -->[[g, f, a], [f, g, h, i, e, d, a], [f, g, h, i, c, b, d, a]] 3 -->[[h, g, f, a], [f, g, h, i, e, d, a], [f, g, h, i, c, b, d, a]] 3 -->[[i, h, g, f, a], [f, g, h, i, e, d, a], [f, g, h, i, c, b, d, a]] R = [i, h, g, f, a] ? ; 4 -->[[e, i, h, g, f, a], [c, i, h, g, f, a], [f, g, h, i, e, d, a], [f, g, h, i, c, b, d, a]]. . 1 -->[[f, g, h, i, c, b, d, a]] 0 -->[] © 2009 Сошников Д. В. Порядок просмотра путей жадным алгоритмом 16
© 2009 Сошников Д. В. Особенности алгоритма Жадный алгоритм учитывает оптимальносить пути с точки зрения эвристики, но не учитывает вес пути Не обеспечивается нахождение кратчайшего пути Хорошо бы иметь алгоритм: Который находит кратчайший путь (допустимый) Который делает это оптимальным образом, с учётом направления на цель 17
© 2009 Сошников Д. В. Алгоритм A В качестве весовой функции при выборе направления поиска будем рассматривать f(X) = g(X) + h(X) A g(X) Где • g(X) – длина текущего пути от начальной вершины до X • h(X) – эвристическая функция • f(X) – весовая функция, по которой осуществляется отбор пути … X … … h(X) Z 18
© 2009 Сошников Д. В. Реализация алгоритма A wt(C: [A|T], H) : - h(A, Z), H is C+Z. place([], L, L). place([X|T], L, R) : - insert(X, L, L 1), place(T, L 1, R). insert(P, [P 1|R], [P, P 1|R]) : - wt(P, C), wt(P 1, C 1), C
© 2009 Сошников Д. В. Порядок просмотра путей алгоритмом A | ? - search_ast(a, i, R). 2 -->[4: [d, a], 2: [f, a]] 3 -->[2: [f, a], 7: [e, d, a], 8: [b, d, a]] 3 -->[7: [e, d, a], 4: [g, f, a], 8: [b, d, a]] 3 -->[4: [g, f, a], 10: [i, e, d, a], 8: [b, d, a]] 3 -->[6: [h, g, f, a], 10: [i, e, d, a], 8: [b, d, a]] 3 -->[9: [i, h, g, f, a], 10: [i, e, d, a], 8: [b, d, a]] R = [i, h, g, f, a] ? ; 4 -->[10: [i, e, d, a], 8: [b, d, a], 12: [e, i, h, g, f, a], 13: [c, i, h, g, f, a]] R = [i, e, d, a] ? ; 5 -->[8: [b, d, a], 12: [e, i, h, g, f, a], 13: [h, i, e, d, a], 13: [c, i, h, g, f, a], 14: [c, i, e, d, a]] 5 -->[12: [e, i, h, g, f, a], 13: [h, i, e, d, a], 12: [c, b, d, a], 13: [c, i, h, g, f, a], 14: [c, i, e, d, a]] 5 -->[13: [h, i, e, d, a], 12: [c, b, d, a], 13: [c, i, h, g, f, a], 14: [c, i, e, d, a], 15: [d, e, i, h, g, f, a]] 5 -->[12: [c, b, d, a], 13: [c, i, h, g, f, a], 14: [c, i, e, d, a], 15: [d, e, i, h, g, f, a], 15: [g, h, i, e, d, a]] 5 -->[16: [i, c, b, d, a], 13: [c, i, h, g, f, a], 14: [c, i, e, d, a], 15: [d, e, i, h, g, f, a], 15: [g, h, i, e, d, a]] R = [i, c, b, d, a] ? ; 6 -->[13: [c, i, h, g, f, a], 14: [c, i, e, d, a], 15: [d, e, i, h, g, f, a], 15: [g, h, i, e, d, a], 19: [e, i, c, b, d, a], 19: [h, i, c, b, d, a]] 6 -->[14: [c, i, e, d, a], 15: [d, e, i, h, g, f, a], 15: [g, h, i, e, d, a], 19: [e, i, c, b, d, a], 19: [h, i, c, b, d, a], 17: [b, c, i, h, g, f, a]]. . . 3 -->[23: [c, b, d, e, i, h, g, f, a], 24: [e, d, b, c, i, h, g, f, a], 23: [f, g, h, i, c, b, d, a]] 2 -->[24: [e, d, b, c, i, h, g, f, a], 23: [f, g, h, i, c, b, d, a]] 1 -->[23: [f, g, h, i, c, b, d, a]] 0 -->[] 20
© 2009 Сошников Д. В. Допустимость алгоритма поиска Алгоритм поиска называется допустимым (admissible), если он в первую очередь находит оптимальный путь в смысле заданного критерия. Поскольку на функцию h(. ) не накладывается никаких ограничений, возможна ситуация, когда «хороший» (оптимальный) путь не рассматривается, т. к. ему соответствует б. Ольшее значение h(. ) Чтобы алгоритм поиска A был допустимым, необходимо наложить ограничения на h(. ) 21
© 2009 Сошников Д. В. Критерий допустимости A* f(X)=g(X)+h(X), где g(X) – длина текущего пути от A до X h(X) – показатель близости конечной вершины Z Раз мы складываем g(. ) и h(. ), логично требовать, чтобы они были одной размерности Реально интересно минимизировать длину оптимального пути f*(X) = g*(X)+h*(X), где g*(X) – длина кратчайшего пути из A в X h*(X) – длина кратчайшего пути из X в Z Теорема. Алгоритм поиска A является допустимым, если для всех вершин графа 0 h(x) h*(x); в этом случае алгоритм поиска называется алгоритмом A*. 22
© 2009 Сошников Д. В. Сравнение алгоритмов поиска Показатель UCS GRD A* Шагов до 1 решения 15 3 6 Макс длина очереди 25 19 22 23
© 2009 Сошников Д. В. Информированность h(x)=0 - удовлетворяет условию допустимости Получаем UCS Чем больше значение функции h(·), тем больше информации об особенностях пространства поиска мы сообщаем алгоритму Определение. Алгоритм эвристического поиска с функцией h 1(x) называется более информированным по сравнению с алгоритмом с функцией h 2(x), если для всех вершин графа x имеет место h 1(x) h 2(x). 24
Определение. Эвристическая функция h(x) называется монотонной, если h(e)=0 для конечного состояния e, и для любых вершин u, v лежащих на одном пути имеет место |h(u)-h(v)| cost(u, v), где cost(u, v) — стоимость пути от u до v. © 2009 Сошников Д. В. Монотонность Теорема. Любая монотонная эвристика допустима. Действительно, для некоторого пути a 1 a 2. . . ane из свойства монотонности следует, что h(ai-1)-h(ai) cost(ai -1, ai), что при суммировании дает h(a 1) = h(a 1)-h(e) cost(a 1, e) = h*(a 1). 25
© 2009 Сошников Д. В. Пример: эвристика для игры в 8 Длина пути измеряется в количестве шагов Эвристическая функция не должна быть больше, чем число шагов до финиша Предлагаем использовать количество фишек не на своих местах dist([], 0). dist([A|T], [B|R], Z) : - dist(T, R, D), ndiff(A, B, E), Z is D+E. ndiff([], 0). ndiff([A|T], [A|R], Z) : - ndiff(T, R, Z), !. ndiff([_|T], [_|R], Z) : - ndiff(T, R, D), Z is D+1. h(S, R) : - final(F), dist(S, F, R). 26
© 2009 Сошников Д. В. Алгоритм IDA* Идею итерационного заглубления можно использовать для реализации A* Тонкие моменты: В ID приращение идет по числу шагов (целочисленное), в IDA* - по длине пути Имеет смысл устанавливать каждый раз некоторый диапазон возможных длин => не гарантируется допустимость в строгом смысле 27
© 2009 Сошников Д. В. Метод градиентного спуска В некоторых случаях пространство состояний имеет очень сложную природу, что не позволяет хранить пути из состояний в памяти Пример: экспертные системы Пример: состояние работающей программы В этих случаях возможно использование алгоритмов поиска, которые рассматривают только одно направление движения Движение в оптимальном направлении даёт нам алгоритм градиентного спуска Оптимальное направление может задаваться эвристической функцией Проблема: остановка в локальном максимуме/минимуме 28
© 2009 Сошников Д. В. Представление списка путей деревом В очереди путей часто присутствует множество путей с общим началом За счёт представления таких путей деревом можно сильно выиграть по памяти [a, b, c] [a, b, d, e] [a, b, d, f] t(a, [t(b, [l(c), t(d, [l(e), l(f)])])]) 29
© 2009 Сошников Д. В. Tree Search search_t(S, F, P) : - t_search(F, l(S), P). t_search(Finish, Tree, Path): - expand(Finish, [], Tree 1, Path), ( nonvar(Path); var(Path), t_search(Finish, Tree, Path)). expand(Finish, Past, l(Finish), _, [Finish|Past]). expand(_, Past, l(Current), t(Current, Sub), _): findall( Next. Leave, t_prolong(Next. Leave, [Current|Past]), Sub). expand(Finish, Past, t(Current, Sub), t(Current, Sub 1), Path): - expand_all(Finish, [Current|Past], Sub, [], Sub 1, Path). t_prolong(l(Next), [Current|Past]): move(Current, Next), not(member(Next, Past)). expand_all(_, _, [], [T|TT], _). expand_all(Finish, Path 0, [T|TT], TT 1, Sub 1, Path): - expand(Finish, Path 0, T, T 1, Path), ( nonvar(Path); var(Path), !, expand_all(Finish, Path 0, TT, [T 1|TT 1], Sub 1, Path); expand_all(Finish, Path 0, TT 1, Sub 1, Path) ). 30
© 2009 Сошников Д. В. Closed Vertex List В рассмотренных методах поиска мы не производили обход уже пройденных вершин в рамках одного пути При откате назад путь укорачивается, и возможно повторное рассмотрение вершины в рамках другого пути Для запоминания пройденных вершин на протяжении всего поиска можно использовать список closed list Глобальные переменные Представление путей парами 31
get_global(G, X) : - value(G, X). store_global(G, X) : - retractall(value(G, _)), asserta(value(G, X)). create_global(G, X) : - asserta(value(G, X)). © 2009 Сошников Д. В. Использование глобального списка пройденных вершин search_cdpth(A, B, L) : - create_global(closed, []), cdpth([A], B, L). cdpth([X|T], X, [X|T]). cdpth(P, F, L) : - cprolong(P, P 1), cdpth(P 1, F, L). cprolong([X|T], [Y, X|T]) : - get_global(closed, C), move(X, Y), not(member(Y, C)), store_global(closed, [Y|C]). get_global(G, X) : - value(G, X). store_global(G, X) : - retractall(value(G, _)), asserta(value(G, X)). create_global(G, X) : - asserta(value(G, X)). 32
© 2009 Сошников Д. В. Поиск с представлением путей парами search_cbdth(X, Y, L) : - cbdth([pair(X, nil)], [], Y, R, C), reconstruct(R, C, L). cbdth([pair(Y, Z)|_], C, Y, pair(Y, Z), C). cbdth([pair(S, P)|Q], C, Y, R, CC) : - findall(Z, prolong(S, Q, C, Z), L), append(Q, L, New. Q), !, cbdth(New. Q, [pair(S, P)|C], Y, R, CC). cbdth([_|Q], C, Y, R, CC) : - cbdth(Q, C, Y, R, CC). prolong(S, Q, C, pair(X, S)) : - move(S, X), not(member(pair(X, _), Q)), not(member(pair(X, _), C)). reconstruct(pair(X, nil), _, [X]). reconstruct(pair(X, Y), L, [X|T]) : - member(pair(Y, Z), L), reconstruct(pair(Y, Z), L, T). 33
© 2009 Сошников Д. В. Представление путей парами 1 --> [pair(a, nil)] : [] 2 --> [pair(d, a), pair(f, a)] : [pair(a, nil)] 3 --> [pair(f, a), pair(e, d), pair(b, d)] : [pair(d, a), pair(a, nil)] 3 --> [pair(e, d), pair(b, d), pair(g, f)] : [pair(f, a), pair(d, a), pair(a, nil)] 3 --> [pair(b, d), pair(g, f), pair(i, e)] : [pair(e, d), pair(f, a), pair(d, a), pair(a, nil)] 3 --> [pair(g, f), pair(i, e), pair(c, b)] : [pair(b, d), pair(e, d), pair(f, a), pair(d, a), pair(a, nil)] R = [i, e, d, a] ? ; 3 --> [pair(i, e), pair(c, b), pair(h, g)] : [pair(g, f), pair(b, d), pair(e, d), pair(f, a), pair(d, a), pair(a, nil)] 2 --> [pair(c, b), pair(h, g)] : [pair(i, e), pair(g, f), pair(b, d), pair(e, d), pair(f, a), pair(d, a), pair(a, nil)] 1 --> [pair(h, g)] : [pair(c, b), pair(i, e), pair(g, f), pair(b, d), pair(e, d), pair(f, a), pair(d, a), pair(a, nil)] 34
© 2009 Сошников Д. В. Мораль Эвристические алгоритмы поиска позволяет сократить пространство перебора за счет введения некоторой «внешней» эвристической функции Для сохранения свойства допустимости эвристическую функцию нужно определять «с умом» Компромисс между критерием допустимости и информированностью Возможно комбинирование эвристических методов с более эффективными способами представления путей в памяти Для сложных случаев используют градиентный эвристический спуск (hill climbing) 35


