Прямая и обратная цепочки рассуждений
На глобальном уровне управления последовательностью применения правил можно выделить две стратегии поведения — применять правила в прямом и обратном порядке. Прямой порядок означает, что цепь рассуждений строится, отталкиваясь от данных (условий, о которых известно, что они удовлетворяются), к гипотезам (состоянию проблемы, вытекающему из этих условий). Обратная цепочка означает, что рассуждения строятся, отталкиваясь от заданной цели (гипотезы, представляющие целевое состояние системы) к условиям, при которых возможно достижение этой цели. Здесь явно чувствуется аналогия с прямой и обратной стратегиями доказательства теорем (см. об этом в главе 8).
CLIPS представляет собой систему, в которой строится прямая цепочка рассуждений, а порождающие правила в системе MYCIN используются в большинстве случаев для построения обратной цепочки рассуждений, как было показано в главе 3. В CLIPS всегда сопоставляются состояние рабочей памяти и левые части правил, а затем выполняются действия, предусмотренные правой частью выбранного правила. А в MYCIN ведущей в рассуждениях является правая часть правила. Если мы задались целью установить природу некоторого микроорганизма, то отбираются все правила, в правой части которых дается соответствующее заключение, и затем анализируется, предпосылки какого из них удовлетворяются текущими данными.
Проще всего представить отличие между прямой и обратной цепочками рассуждений в терминах грамматических правил, аналогичных представленным в разделе 5.1. Как было показано, набор правил
(Р1) $ -> а$а
(Р2) $ -> b$b
(РЗ) $ -> с$с
можно использовать двумя способами.
Во-первых, их можно использовать для формирования палиндромов. Если задаться некоторым начальным символом из имеющегося алфавита, то любая последовательность применения правил приведет к формированию палиндрома. Так, применение правил Р1, Р1, РЗ, Р2, Р3 к исходному символу с приведет к формированию строк
аса, aacaa, caacaac, bcaacaacb, cbcaacaacbc.
Это пример прямой цепочки, поскольку с и каждая последующая сформированная строка сопоставляются с левой частью правила, а затем означивается правая часть правила.
Во-вторых, можно использовать этот же набор правил не для формирования, а для распознавания палиндромов. Мы уже видели ранее, что, задавшись некоторой строкой, например ЬасаЬ, можно проследить, в какой последовательности применялись правила при построении этой строки. Строка bасаb соответствует правой части правила Р2; можно сказать, что правая часть правила Р2 "допускает" строку bacab. Означенная левая часть правила Р2 — это строка аса, которая соответствует правой части правила PI, a означенная левая часть этого правила — аксиома с. Таким образом, процесс распознавания успешно завершился — мы доказали, что bacab представляет собой палиндром. Описанный процесс распознавания — это пример применения обратной цепочки рассуждений. Начальная строка bacab и каждая очередная подстрока анализируются на соответствие с правыми частями имеющихся правил, а результатом является означивание левой части выбранного правила. Если в качестве исходной мы зададимся строкой acbcb, то для нее не удастся найти в имеющемся наборе правил такое, правая часть которого "допускала" бы эту строку, а значит, исходная строка не может быть палиндромом.
В литературе по теории доказательства теорем прямая цепочка рассуждений, как правило, ассоциируется с "восходящим" процессом, т.е. рассуждениями от фактов к целям, а обратная цепочка — с "нисходящим" процессом, рассуждением от целей к фактам. Но, строго говоря, в отношении продукционных систем эти термины не являются синонимами. Например, вполне возможно реализовать нисходящий процесс в продукционной системе с прямой цепочкой рассуждений, если должным образом настроить локальный режим управления, например задать явное указание целей.
В листинге 5.4 показана простая программа построения башни из блоков. Эта программа переключается между двумя задачами: выбором очередного блока и установкой блока в башню.
В разделе шаблонов блоки представлены объектами, обладающими такими свойствами, как цвет, размер и положение.
Если положение блока не определено, предполагается, что он находится в куче блоков (heap), еще не уложенных в башню. Шаблон on предоставляет в наше распоряжение средство, позволяющее описать размещение блоков одного (upper) на другом (lower). Информацию о текущей фазе решения проблемы (поиск или установка) несет шаблон goal.
Листинг 5.4. Набор правил для построения башни из блоков
;; СТРАТЕГИЯ РАЗРЕШЕНИЯ КОНФЛИКТОВ
(declare (strategy mea))
;; Шаблоны
;; Объект block характеризуется цветом, размером и положением,
(deftemplate block
(field color (type SYMBOL))
(field size (type INTEGER))
(field place (type SYMBOL)) )
;; Вектор 'on' указывает, что блок <upper>
;; находится на блоке <lower>. (deftemplate on
(field upper (type SYMBOL»
(field lower (type SYMBOL))
(field place (type SYMBOL) (default heap)] )
;; Текущая цель (goal) может быть либо 'найти' (find),
;; либо 'уложить' (build), (deftemplate goal
(field task (type SYMBOL)) )
;; ИНИЦИАЛИЗАЦИЯ
;; Имеются три блока разных цветов и размеров.
;; Предполагается, что они находятся в куче.
(deffacts the-facts
(block (color red) (size 10))
(block(color yellow) (size 20))
(block (color blue) (size 30))
)
;; ПРАВИЛА
;; Задать первую цель: найти первый блок,
(defrule begin
(initial-fact) =>
(assert (goal (task find))) )
;; Взять самый большой блок в куче (heap),
(defrule pick-up
?my-goal <- (goal (task find))
?my-block <- (block (size ?S1) (place heap))
(not (block (color ?C2) (size ?S2&:(>-?S2 ?S1))
(place heap))) =>
(modify ?my-block (place hand))
(modify ?my-goal (task build)) )
;; Установить первый блок в основание башни (tower).
;; Этот блок не имеет под собой никакого другого,
(defrule place-first
?my-goal <- (goal (task build))
?my-block <- (block (place hand))
(not (block (place tower)))
=>
(modify ?my-block (place tower))
(modify ?my-goal (task find)) )
;; Установить последующие блоки на тот,
;; что лежит в основании башни,
(defrule put-down
?my-goal <- (goal (task build))
?my-block <- (block (color ?C0)
(place hand))
(block (color ?C1) (place tower)))
(not (on (upper ?C2) (lower ?C1)
(place tower)))
=>
(modify ?my-block (place tower))
(assert (on (upper ?CO) (lower ?C1)
(place tower)))
(modify ?my-goal (task find)) )
;; Если в куче больше нет блоков, прекратить процесс,
(defrule stop
?my-goal <- (goal (task find))
(not (block (place heap)))
=>
(retract ?my-goal) )
Обратите внимание на то, что порядок перечисления правил в программе не имеет значения. В программе управления роботом, представленной в листинге 5.3, правило прекращения выполнения стояло в списке первым, а в этой программе оно стоит в самом конце списка. Трассировку выполнения приведенной программы и некоторые комментарии вы найдете во врезке 5.4.
5.4. Трассировка программы строительства башни
При запуске программы в режиме трассировки будет сформирована следующая карта трассировки.
CLIPS> (reset)
==> f-0 (initial-fact)
==> f-1 (block (color red) (size 10) (place heap))
==>f-2 (block (color yellow) (size 20) (place heap))
==> f-3 (block (color blue) (size 30) (place heap))
CLIPS> (run)
TIRE 1 begin: f-0
==> f-4 (goal (task find))
FIRE 2 pick-up: f-4, f-3,
<== f-3 (block (color blue) (size 30) (place heap))
==> f-5 (block (color blue) (size 30) (place hand))
<== f-4 (goal (task find))
==> f-6 (goal (task build))
FIRE 3 place-first: f-6, f-5,
<== f-5 (block (color blue) (size 30) (place hand))
==> f-7 (block (color blue) (size 30) (place tower))
<== f-6 (goal (task build))
==> f-8 (goal (task find))
FIRE 4 pick-up: f-8, f-2,
<== f-2 (block (color yellow) (size 20) (place heap))
==> f-5 (block (color yellow) (size 20) (place hand))
<== f-8 (goal (task find))
==> f-10 (goal (task build))
FIRE 5 put-down: f-10, f-9, f-7,
<== f-9 (block (color yellow) (size 20) (place hand))
==>. f-11 (block (color yellow) (size 20) (place tower))
==> f-12 (on (upper yellow) (lower blue) (place tower))
<== f-10 (goal (task build))
==> f-13 (goal (task find))
FIRE 6 pick-up: f-13, f-1,
<== f-1 (block (color red) (size 10) (place heap))
==> f-5 (block (color red) (size 10) (place hand))
<== f-13 (goal (task find))
==> f-15 (goal (task build))
FIRE 7 put-down: f-15, f-14, f-11,
<== f-14 (block (color red) (size 10) (place hand))
==> f-16 (block (color red) (size 10) (place tower))
==> f-17 (on (upper red) (lower yellow) (place tower))
<== f-15 (goal (task build))
==> f-18 (goal (task find))
FIRE 8 stop: f-18,
<== f-18 (goal (task find))
CLIPS> (reset)
<== f-0 (initial-fact)
<== f-7 (block (color blue) (size 30) (place tower))
<== f-11 (block (color yellow) (size 20) (place tower))
<== f-12 (on (upper yellow) (lower blue) (place tower))
<== f-16 (block (color red) (size 10) (place tower))
<== f-17 (on (upper red) (lower yellow) (place tower))
Обратите внимание на манипулирование лексемой цели в ходе выполнения программы. Конечное состояние представлено при очистке рабочей памяти. Блоки в башне расположились в таком порядке: красный (red) — самый верхний, он стоит на желтом (yellow), который стоит на синем (blue).
Особенность этого примера в том, что в программе реализована нисходящая стратегия рассуждений, хотя правила предполагают использование прямой цепочки анализа данных, т.е. "работают" в направлении снизу вверх. Этот эффект достигается манипулированием лексемами цели. В данном случае выражение (initial-fact) формулирует цель верхнего уровня — построить башню. Эта цель имеет две подцели — поиск блока и установка блока в башню, которые представлены лексемами
(goal (task find)
и
(goal (task build)).
Когда оказывается, что в куче больше нет блоков, главная цель достигнута. Мы делаем это в определенной степени неформально, используя (initial-fact) для упрощения программного кода, но принцип, тем не менее, соблюдается.
Иногда необходимо провести четкую границу между направленностью цепочки и направленностью действительных рассуждений. Эти две операции представляют разные уровни анализа. Очевидно, что цепочка является реализацией рассуждений, а не наоборот, но стратегия рассуждений управляет процессом построения цепочки, что в данном случае выполняется манипулированием лексемами цели. В главе 14 будет продемонстрирован гораздо более сложный пример использования этого метода в системе R1/XCON.
Это разделение высвечивает проблему, с которой очень часто приходится сталкиваться при обсуждении функционирования программ искусственного интеллекта. Большинство сложных систем, независимо от того, являются ли они программными системами, или физическими устройствами, или комбинацией тех и других, могут быть описаны на разных уровнях [Newell, 1982]. В соответствии с терминологией Ньюэлла, построение цепочки — это свойство символического уровня, где нас интересуют только левые и правые части правил, а рассуждение— это нечто, возникающее на уровне знаний, где можно провести разделение между фактами и задачами.
Ранее уже утверждалось, что большинство порождающих правил, представляющих реальный интерес с точки зрения приложений искусственного интеллекта, являются недетерминированными. При построении прямой цепочки рассуждений может оказаться, что текущие данные удовлетворяют предпосылки не одного правила, а нескольких. При построении обратной цепочки также зачастую оказывается, что одна и та же цель достигается при выполнении не единственного правила, а нескольких. Поэтому понятно, какая важная роль отводится механизму управления правилами в функционировании продукционной системы.
В главе 3 мы рассказывали о представлении пространства поиска, связанного с набором порождающих правил, с помощью И/ИЛИ-дерева. Узлы такого дерева соответствуют состояниям рабочей памяти, а дуги — правилам, которые при этом возможно применить. Древовидная схема очень хорошо согласуется с методикой обратной цепочки рассуждений, если считать, что корень дерева соответствует целевому состоянию, промежуточные узлы — подцелям, а терминальные узлы (листья) — данным.
В И/ИЛИ-дереве корень представляет исходное состояние проблемы, а листья — возможные варианты ее решения. Нетерминальные узлы могут быть двух видов: И-узлы и ИЛИ-узлы. И-узлы соответствуют применению нескольких правил, которые в совокупности формируют цель как объединение нескольких подцелей, а ИЛИ-узлы соответствуют наличию альтернативы при выборе возможных правил. Таким образом, используя терминологию главы 2, можно говорить о том, что возможные варианты применения правил формируют пространство поиска и определяют его структуру.
Программирование, основанное на правилах (логическое программирование), не снимает с повестки дня проблему комбинаторного взрыва, поскольку для любой проблемы И/ИЛИ-дерево может ветвиться по экспоненциальному закону. Но на практике стратегия разрешения конфликтов, реализованная в интерпретаторах правил, позволяет надеяться на отыскание разумного решения.