4.3.5.
Сопоставление с образцом
Одним из ключевых
компонентов в большинстве программ искусственного интеллекта является анализатор
соответствия (pattern matcher) — компонент, который некоторым образом сравнивает
поступающие на его вход списки (или другие структуры данных) с имеющимися символическими
образцами и таким образом выполняет распознавание входных данных.
В главе 3
мы обращали ваше внимание на то, что факты, относящиеся к состоянию окружающего
мира, представляются в форме "предикат— аргумент". Тот факт, что робот
находится в комнате, был представлен в модели мира формулой
at(robot,
room). На языке LISP этот факт будет представлен символическим выражением
(at robot
room). Положим, что ? — символ универсальной подстановки и что выражение
(at robot ?) представляет собой образец, которому соответствует и выражение
(at robot
room), и другое выражение в форме
(at robot
blah),
где blah
— любой символ. На языке LISP несложно разработать простой анализатор соответствия,
который будет сравнивать два ординарных списка (т.е. списка, на имеющего подсписков
в качестве элементов) и возвращать значение TRUE, если один из них, sample (пример),
можно представить как реализацию другого — pattern (образец). Текст такой программы
приведен ниже. Предполагается, что образец может иметь любую конечную длину
и содержать любое количество символов универсальной подстановки.
(defun
match (sample pattern)
(cond ((and (null sample)
(null pattern)) T) ((or
(null sample) (null pattern)) NIL)
((eq
(first pattern '?))
(match (rest sample) (rest pattern)))
((eq (first sample) (first pattern))
(match (rest sample) (rest pattern)))
(T
NIL)) )
Обращение
к этой функции в выражении
(match '(at robot room) '(at robot ?))
даст результат Т, а обращение
(match
'(at box room) '(at robot ?))
даст
результат NIL.
Можно усовершенствовать
приведенный анализатор соответствия. Например, сделать так, чтобы он различал
другой символ универсальной подстановки в качестве переменной, которой может
быть присвоено значение символа, соответствие с которым анализируется. Например,
образцу
(at
?X ?Y)
должен соответствовать
пример
(at
robot room),
который образуется
при подстановке {?X/robot, ?Y/room}, как об этом говорилось в главе 3. Можно
также потребовать, чтобы присвоение значений переменным было совместимым, т.е.
чтобы пример
(at
robot room)
не соответствовал
образцу
(at
?Х ? X).
Но, как мы
видели в главе 3, главное назначение анализатора соответствия — показать, что
имеющаяся в программе модель мира удовлетворяет условиям некоторого правила,
которое в таком случае программа сможет затем применить. Пусть в программе имеется
простое правило, утверждающее, что все объекты, находящиеся в комнате, нужно
покрасить:
if
(at ?X room) then (paint ?X)
Нужно проверить,
соответствует ли условию if (at ?X room) этого правила модель мира, представленная
списком
(at
box room).
Полученную
подстановку {?X/box} применим затем к констатирующей части правила и получим
в результате
(paint
box).
Анализ соответствия — это довольно "расточительная" операция в смысле расхода вычислительных ресурсов, если только не пользоваться ею с умом. В главе 13 мы увидим, что существуют довольно эффективные алгоритмы, которые позволяют решить, в каких именно из имеющихся в наборе правилах (или отдельном правиле) сформулированы условия, соответствующие анализируемым данным. В настоящее время язык LISP не используется для реализации систем, базирующихся на правилах, в основном из-за недостаточной его эффективности, но по-прежнему используется тот принцип обработки списков при анализе соответствия, который был впервые реализован на LISP.