Методы искусственного интеллекта для синтеза проектных решений. Подольский В.Е - 40 стр.

UptoLike

6.7. ПРИМЕРЫ ФУНКЦИЙ РАБОТЫ СО СПИСКАМИ
При работе со списками могут потребоваться дополнительные функции, которые требуют написания соответствующих
предикатов.
Предположим, что имеется некоторый список, в котором X обозначает его голову, а Y – хвост (т.е [X|Y]).
6.7.1. Принадлежность элементов списку
Требуется определить, содержится ли некоторый объект в указанном списке. В Прологе это можно сделать, определив,
совпадает ли этот объект с головой списка. Еслида, то наш поиск завершается успехом. Еслинет, то проверяем, есть ли
объект в хвосте исходного списка, а значит снова проверяется голова, но уже хвоста списка. Затем проверяется голова
очередного хвоста списка. Если мы доходим до конца списка, то наш поиск завершается неудачей: указанного объекта в
списке нет.
Для того чтобы записать все это на Прологе, сначала необходимо установить отношение принадлежности между
объектом и списком.
У нас есть два условия, которые надо проверить:
1)
X является элементом списка Y, если X совпадает с головой списка Y.
2)
X является элементом списка Y, если X входит в хвост списка Y. Для проверки этого условия можно использовать
рекурсию.
Таким образом, можно записать:
domains
L=symbol*
predicates
yes(symbol, L).
clauses
yes(X, [X|_]) :- write(“yes”).
yes(X, [_|Y]) :- yes(X,Y).
goal
clearwindow, yes(d, [a,b,c,d,e,f]).
Результатом работы этой программы будет ответ “yes”, так как элемент d входит в список [a, b, c, d, e, f]. Наиболее
важный момент, о котором следует помнить, встретившись с рекурсивно определённым предикатом, заключается в том, что,
прежде всего надо найти граничные условия и способ использования рекурсии.
Для рассмотренного предиката yes имеются два типа граничных условий. Либо объект, который мы ищем, содержится в
списке, либо он не содержится в нём. Первое граничное условие для предиката yes распознается первым правилом, которое
приведёт к прекращению поиска в списке, если первый аргумент предиката совпадает с головой списка, соответствующего
второму аргументу.
Второе граничное условие не распознается ни одним из утверждений, но рекурсивные вызовы предиката yes во втором
правиле будет продолжаться до тех пор, пока хвост списка не станет пустым. В этом случае поиск является неудачным.
6.7.2. Определение длины списка
Данную функцию также можно реализовать с помощью рекурсии:
domains
L=symbol*
predicates
len(L,integer).
clauses
len([],0).
len([_|HV],D) :- len(HV,T), D=T+1.
goal
len([a,b,c,d,e,f],D), write(D).
Результатом работы такой программы будет число 6.
6.7.3. Разделение строки на слова с занесением их в список
Данную функцию можно выполнить аналогично, используя рекурсию:
decompose(“”,[]).
decompose(X, [X1|T]) :- fronttoken(X,X1,X2), decompose(X2,T).
Граничное условие в данном случаеэто пустая строка, аналогом которой является пустой список.
В данном примере используется встроенный предикат:
fronttoken(Строка, Лексема, Остаток),
который разделяет строку на лексему и остаток. В данном случае Строка, Лексема, Остаток имеют тип string. Например, в
результате выполнения предиката
fronttoken(“Мама мыла раму”, X, Y),
переменной X будет присвоено значениеМама”, а переменной Y – значениемыла раму”.