дб. Четвертое издание джозеф Джарратано Университет Хьюстон клиэрЛэйк Гари Райли People5oft, Издательский дом "Вильямс" Москва СанктПетербург Киев 2007 ббк 32. 973. 26 018 75 Д
Скачать 3.73 Mb.
|
9084))) (defrule print-social-security-numbers (print-ss-numbers-for ? last-name) (person (name пате пате ?last-name) (social-security-number ?ss-number)) — > (printout t ?ss-number crlf)) Правило print — social — security-numbers связывает имя и отчество рассматриваемого лица соответственно с переменными ? пате и ?middle — name. Нона эти переменные нет ссылок либо в действиях правой части правила или в других шаблонах, либо в слотах в левой части правила Вместо использования переменной, когда потребуется подстановка некоторого поля, но его значение не представляет интереса, можно применить однозначный подстановочный символ, который представляет собой вопросительный знак. С помощью однозначных подстановочных символов правило print — social — security— numbers можно перезаписать следующим образом (defrule print-social-security-numbers (print-ss-numbers- for ?last-name) (person (name ? ? ?last-name) (social-security- number ?ss-number)) — > (printout t ?ss-number crlf)) Обратите внимание на то, что слот name факта person должен содержать точно три поля, чтобы обеспечивалась возможность активизировать правило print— social — Например, следующий факт не будет удовлетворять правилу print — social — security — numbers: (person (name Joe Public) (social-security-number 345-89-3039)) Следует отметить, насколько важно не включить пробел между вопросительным знаком и символическим именем переменной. В частности, такой шаблон предусматривает использование двух полей для слота name: (person (name ?first ?last)) а следующий шаблон предусматривает применение для слота пате трех полей, причем последним полем должен быть символ last: (person (name ?first ? last)) Если в некотором шаблоне остается незаданным некоторый однозначный слот, то система автоматически трактует его таким образом, как если бы для это. Мир блоков 601 го слота была предусмотрена проверка с помощью однозначного подстановочного символа. Например, шаблон (person (name ?first ?last)) эквивалентен такому шаблону (person (name ?first ?last) (social-security-number ?)) 7.23 Мир блоков Для демонстрации возможностей средств связывания переменных разработаем программу, управляющую перемещением блоков в простом мире блоков. Программа такого типа аналогична классической программе для мира блоков, в которой область знаний ограничена теми знаниями, которые касаются блоков [25, с. 224 — 226]. Решение задачи перемещения блоков представляет собой полноценный пример планирования, которое может применяться для автоматизации производственных процессов, связанных с перемещением деталей с помощью манипулятора. В мире блоков интерес представляют только блоки. Блоки могут складываться в столбики с учетом того, что на каждый блок может устанавливаться один и только один блок. Перед программой в мире блоков ставится цель — изменить взаимное расположение блоков в столбиках и получить требуемую конфигурацию с помощью минимального количества ходов. В рассматриваемом примере можно принять целый ряд упрощающих ограничений. Первое из этих ограничений состоит в том, что допускается лишь одна начальная цель, которая может состоять только в том, чтобы один блок был перемещен на верхнюю поверхность другого. Благодаря этому ограничению задача определения оптимальных ходов, позволяющих достичь намеченной цели, становится довольно тривиальной. Если цель состоит в том, чтобы переместить блок хна верхнюю поверхность блока у, то достаточно переместить все блоки (если таковые имеются), стоящие над блоком хна пола также переместить на пол все блоки, стоящие на блоке у (если таковые имеются, а затем поставить блок хна блоку. В качестве второго ограничения можно принять такое условие, чтобы не выдвигалась какая-либо цель, которая уже была достигнута. Это означает, что цель не может состоять в перемещении блоках на блоку, если блок хуже стоит на блоке у. Проверка соблюдения такого условия является довольно простой тем не менее синтаксис, с помощью которого можно было бы проверить соблюдение указанного условия, будет представлен только в главе 8. Прежде чем приступить к решению сформулированной задачи, целесообразно определить конфигурацию блоков, которая должна использоваться для проверки программы. Применяемая конфигурация показана на рис. 7.2. Эта конфигурация 602 Глава 7. Введение в CLIPS состоит из двух столбиков. В первом столбике блок A стоит на блоке В, стоящем на блоке С. Во втором столбике блок D стоит на блоке Е, стоящем на блоке. Рис. 7.2. Начальная конфигурация в мире блоков Чтобы определить, какие типы правил позволят эффективно решить эту задачу, имеет смысл попытаться достичь цели в мире блоков, рассматривая последовательно один ход за другим. Какие этапы должны быть выполнены для перемещения блока Сна блок Е Простейшим решением этой задачи было бы непосредственное перемещение Сна Е. Но правило, подразумевающее такое решение, можно было бы применить, только если ни на блоке С, ни на блоке Е не стоят другие блоки. Ниже приведен псевдокод для данного правила. RULE МОЧЕ IF The goal is to move block ?upper on top of block ? lower and block ?upper is the top block in its stack and block ?lower is the top block in its stack, THEN Моче block ?upper on top of block ?lower. В рассматриваемом случае правило move — directly использовать невозможно, поскольку на блоке С стоят блоки Аи В, а на блоке Е стоит блок D. Для того чтобы обеспечить применение правила move-directly для перемещения блока Сна блок Е, необходимо переместить блоки А, Вина пол. Поскольку это — простейший способ избавиться от указанных блоков, именно они применяется. В рассматриваемом простом мире блоков не требуется, чтобы блоки снова устанавливались в другие столбики, кроме того, допускается лишь единственная начальная цель, поэтому не требуется составлять блоки в столбики при удалении их таким образом. Данное правило может быть выражено в виде двух приведенных ниже правил на псевдокоде одно правило предназначено для снятия блоков с того блока, который подлежит перемещению, а другое правило позволяет сни- 7.23. Мир блоков 603 мать блоки с того блока, на который в дальнейшем должен быть поставлен другой блок. CLEAR- UPPER-BLOCK The доа1 is to move block х and block х is not the top block in its stack and block ?above is on top of block х, The goal is to move block ?above to the floor CLEAR-LOWER-BLOCK The goal is to move another block on top of block х and block х is not the top block in its stack and block ?above is on top of block х goal is to move block ?above to the floor RULE IF THEN RULE IF THEN RULE МОЧЕ-ТО-FLOOR IF The goal is to move block ? upper on top of the floor and block ?upper is the top block in its stack, THEN Моче block ?upper on top of the floor. Теперь можно воспользоваться правилом move — to — floor для перемещения блоков Аи на пол. А после перемещения на пол блока А правило move — tofloor можно активизировать для перемещения на пол блока В. Наконец, после того как блоки А, В и D будут на полу, блоки Си Е окажутся верхними блоками своих столбиков и поэтому появится возможность применить правило move — directly для перемещения блока Сна блок Е. После формулировки необходимых правил на псевдокоде необходимо приступить к определению фактов, которые будут использованы в правилах. Следует С помощью правила clear — upper — block блоки будут сниматься с блока С. Это правило вначале позволяет определить, что на пол следует переместить блок В. Кроме того, тоже самое правило позволит определить, что для перемещения на пол блока В необходимо переместить на пол блок А. Аналогичным образом, правило clear — lower — block позволяет определить, что на пол необходимо переместить блок, для того чтобы можно было что-то поставить на блок Е. К этому времени появились следующие подцели: переместить на пол блоки А, В и D. Блоки Аи могут быть сразу же перемещены на пол. Если правило move — directly будет сформулировано должным образом, то сего помощью появится возможность обеспечить перемещение, наряду с другими блоками, а также и блоков, находящихся на полу. Дело в том, что пол фактически не является блоком, поэтому может потребоваться трактовать связанные с ним операции подругому. Ниже приведено правило на псевдокоде, в котором учитывается частный случай перемещения блока на пол 604 Глава 7. Введение в CLIPS отметить, что без подготовки некоторых прототипов не всегда удается установить необходимые типы фактов. А в данном случае на необходимость применения нескольких типов фактов указывают сами правила, сформулированных на псевдокоде. Например, очень важна информация о том, какие блоки стоят на других блоках. Эту информацию можно представить с помощью следующей конструкции deftemplate: (deftemplate on-top-of (slot upper) (slot lower)) Факты, описанные с помощью этого шаблона, принимают такой вид (on-top-of (upper А) (lower ВВС ЕЕ) Важно также знать, какие блоки находятся в верхней и нижней частях каждого столбика, поэтому следует включить такие факты (on-top-of (upper nothing) (lower АС) В этих фактах слова nothing и floor имеют особый смысл. Факты (ontop-of (upper nothing) Аи) указывают, что Аи являются самыми верхними блоками в своих столбиках. Аналогичным образом, факты (on — top-of (upper С) (lower floor)) v (on — toð-of (upper F) (lower Й1оог))показывают, что нижними блоками в своих столбиках являются блоки Си. Но включение этих фактов необязательно должно привести к решению задачи определения верхнего и нижнего блоков в столбике. Если правила не будут сформулированы должным образом, то ключевые слова floor и nothing будут неправильно трактоваться как имена блоков. Поэтому могут потребоваться также факты, позволяющие указывать имена блоков. Ниже перечислены факты, в которых используется подразумеваемая конструкция deftemplate с именем block, которые позволяют отличать имена блоков от специальных слови ВСЕ. Мир блоков 605 Наконец, требуется факт, позволяющий описывать достигаемые цели перемещения блоков. Эти цели можно описать с помощью следующей конструкции deftemplate: (deftemplate goal (slot move) (slot on-top-of)) В качестве начальной цели сформулируем с помощью конструкции de f template следующую цель (goal (move СЕ) Итак, на данный момент определены все факты и конструкции de й, поэтому можно описать начальную конфигурацию рассматриваемого мира блоков с помощью такой конструкции de f f acts: (deffacts initial-state (block А) (block ВСЕ А) (lower ВВС СЕ Е) (lower F)) (on-top-of (upper F) (lower floor)) (goal (move СЕ) Правило move — directly записывается следующим образом (defrule move-directly ?goal <- (goal (move ?block1) (on-top-of ?block2)) (block ?block1) (block ?block2) (on-top-of (upper nothing) (lower ?block1)) ?stack-1 <- (on-top-of (upper ?block1) (lower ?block3)) ?stack-2 <- (on-top-of (upper nothing) (lower ?block2)) => (retract ?goal ?stack-1 ?stack-2) 606 Глава 7. Введение в CLIPS (assert (on-top-of (upper ?block1) (lower ?block2)) (on-top-of (upper nothing) (lower ?block3))) (printout t ?block1 " moved on top of " ?block2 crlf)) Первые три шаблона определяют, что задана цель перемещения одного блока на другой блок, при этом второй и третий шаблоны исключают возможность достижения с помощью данного правила цели перемещения какого-либо блока на пол. С помощью четвертого и шестого шаблонов проверяется, являются ли рассматриваемые блоки верхними блоками в своих столбиках. Пятый и шестой шаблоны согласуются с информацией, необходимой для обновления состояния столбиков, с которых снимаются и на которые ставятся перемещаемые блоки. Обновление информации о столбиках, относящейся к обоим столбиками вывод сообщения осуществляются с помощью действий правила. При этом учитывается условие, что блок, находившийся под снятым блоком, становится верхним блоком в своем столбике, а блок, поставленный на другой блок, становится верхним блоком в том столбике, в который он перенесен. Правило move — to — floor реализовано следующим образом (defrule move-to-floor ?goal <- (goal (move ?block1) (on- top-of floor)) (block ?block1) (on-top-of (upper nothing) (lower ? block1)) ?stack <- (on-top-of (upper ?block1) (lower ?block2)) => (retract ?goal ?stack) (assert (on-top-of (upper ?block1) (lower floor)) (on-top-of (upper nothing) (lower ?block2))) (printout t ?blockl " moved on top of floor." crlf)) Это правило аналогично правилу move-directly, за исключением того, что информацию о состоянии пола обновлять не требуется, поскольку пол — не блок. Правило clear — upper — block реализовано следующим образом (defrule clear-upper-block (goal (move ?block1)) (block ? block1) 7.23. Мир блоков 607 (on-top-of (upper ?block2) (lower ?block1)) (block ?block2) > (assert (goal (move ?block2) (on-top-of Правило clear — lower — block реализовано следующим образом (defrule clear-lower-block (goal (on-top-of ?block1)) (block ?block1) (on-top-of (upper ?block2) (lower ?block1)) (block ?block2) — > (assert (goal (move ?block2) (on-top-of floor)))) На этом разработка программы, состоящей из правили конструкций de f template с именами goal и on — top-of, а также конструкции de ffacts с именем initial — state, завершается. Пример прогона этой программы для мира блоков показан в следующем выводе CLIPS> (unlatch all)J CLIPS> (reset)J CLIPS> (run)J А moved on top of floor. ВСЕ Вначале на пол перемещаются блоки Аи В для освобождения блока С. Затем на пол перемещается блок D для освобождения блока Е. Наконец, появляется возможность переместить блок Сна блок Е и решить задачу по достижению исходной цели. В этом примере показано, как разрабатывается программа с использованием поэтапного метода. Вначале правила записываются на псевдокоде формулировки которого напоминают текст на естественном языке. Затем эти правила на псевдокоде используются для того, чтобы определить, факты какого типа потребуются в программе. После этого определяются конструкции de f template с описанием проектируемых фактов и с помощью этих конструкций de f template формулируются начальные знания, относящиеся к данной программе. Наконец, правила на Глава 7. Введение в CLIPS 608 псевдокоде преобразуются вправила, а в качестве руководящих указаний для такого преобразования используются конструкции de f template. Для разработки экспертной системы, как правило, требуется значительно больший объем работы по созданию прототипов и приходится проводить намного больше итераций, чем в данном примере. Кроме того, не всегда возможно определить наилучший метод представления фактов или выбрать правила таких типов, которые обеспечат успешное создание экспертной системы. Тем не менее соблюдение единообразной методологии может помочь при разработке экспертной системы, даже если потребуется создание большого количества прототипов и использование нескольких итераций разработки. Многозначные подстановочные символы и переменные Многозначные подстановочные символы Многозначные подстановочные символы и переменные могут применяться для согласования с полями шаблона, количество которых может составлять от нуля и больше. Многозначный подстановочный символ обозначается знаком доллара, за которым следует вопросительный знаки представляет количество вхождений некоторого поля, составляющее от нуля и больше. Следует отметить, что обычные переменные и подстановочные символы согласуются точно с одним полем. На первый взгляд это различие кажется незначительным, но является очень важным. В качестве примера использования многозначных подстановочных символов еще раз рассмотрим правило print — social — security — numbers, описанное в разделе 7.22: (defrule print-social-security-numbers (print-ss-numbers-for ?last-name) (person (name ? ? ?last-name) (social-security-number ?ss- number)) => (printout t ? ss — number crl f ) ) Это правило согласуется только с таким слотом пате, в котором имеются точно три поля. Поэтому следующий факт не согласуется сданным правилом (person (name Joe Public) (social-security- number 345-89-3039)) Но если два однозначных подстановочных символа будут заменены одним многозначным подстановочным символом (как показано ниже, то шаблон person 7.24. Многозначные подстановочные символы и переменные станет согласовываться с любым слотом пате, содержащим по меньшей мере одно поле и включающим в качестве своего последнего поля указанное имя лица (defrule print-social- security-numbers (print-ss-numbers-for ?last-name) (person (name ss-number crlf)) Аналогичным образом, если в шаблоне останется незаданным какой-либо многозначный слот, то система CLIPS будет автоматически трактовать эту ситуацию так, как если бы для данного слота была предусмотрена проверка многозначного подстановочного символа. Например, шаблон (person (social-security-number эквивалентен шаблону (person (name $?) (social-security-number ?ss-number)) Многозначные переменные Однозначные переменные обозначаются префиксом ?, а многозначные переменные — префиксом $?. Ниже приведены конструкции, которые показывают, как вывести список имен всех детей указанного лица. (deftemplate person (multislot name) (multislot children)) (deffacts some-people (person (name John Q. Public) (children Jane Paul Mary)) (person (name Jack R. Public) (children Rick))) (defrule print-children (print-children $?name) (person (пате) (children $?children)) (printout t ?name " has children " ? children crlf)) Первый шаблон правила print — children связывает имя лица, для которого должен быть создан список имен детей, с переменной пате. Второй шаблон 610 Глава 7. Введение в CLIPS согласовывает факт person с указанным именем, содержащимся в переменной $? пате, а затем связывает список детей этого лица с переменной $? children. После этого полученное значение выводится с помощью действия, заданного в правой части указанного правила. Обратите внимание на то, что при формировании ссылки на многозначную переменную в правой части правила необязательно включать знак $ в состав имени переменной. Знак используется только в левой части для указания на то, что количество полей, которые могут быть связаны с этой переменной, составляет от нуля и больше. Ниже приведен диалог, который демонстрирует действие правила print— children. CLIPS> (reset)J CLIPS> (assert (print-children John Q. Public))J (Jane Paul Mary) CLIPS> Обратите внимание на то, что при выводе на внешнее устройство многозначные значения, связанные с переменными ?name и ?children, заключаются в круглые скобки. В каждом отдельном слоте допускается использование больше чем одной многозначной переменной. Предположим, например, что требуется найти всех людей, имеющих ребенка с указанным именем. Данная задача решается с помощью следующего правила (defrule find — child (find-child ?child) (person (name $?name) (children $?before ?child $?after)) => (printout t ?name " has child " ?child crlf) (printout t "Other children are ?before " " ?after crlf)) Вообще говоря, если бы нас интересовало только значение переменной ? child, то переменные $?before и $? af ter можно было бы заменить многозначными подстановочными символами (и удалить оператор printout, в котором упоминаются эти переменные). Ниже приведен диалог, который показывает, как действует такое правило find — child. CLIPS> (reset)J CLIPS> (assert (find-child Paul))J 7.24. Многозначные подстановочные символы и переменные 611 () () CLIPS> (assert (find-child Bill))J CLIPS> Если с переменной ? child связывается имя ребенка, то с переменной 9?before связывается значение ( 7апе), ас переменной $?after — значение (Mary) . Аналогичным образом, если с переменной ? child связывается значение Rick, то с переменной $? be f ore связывается значение ( ), т.е. многозначное значение, содержащее нуль полей, ас переменной $?after также связывается значение () Применение нескольких различных способов согласования с шаблонами CLIPS> (agenda)J 0 find-child: f-4,f-3 0 find-child f— - 4, f — 3 0 find-child: f-4,f-3 For а total of 3 activations. До сих пор в данной главе рассматривались лишь такие ситуации, в которых единственный факт мог быть согласован с шаблоном только одним способом. Если же используются многозначные переменные или подстановочные символы, то появляется возможность согласования с шаблоном больше чем одним способом. Предположим, что введен факт сданными о некотором лице, назвавшем всех своих детей также, как зовут его CLIPS> (reset)J CLIPS> (assert (person (name Joe Fiveman) (children Joe Joe Глава 7. Введение в CLIPS 612 CLIPS> (run)J (Joe Fiveman) has child Joe Other children are () (Joe Joe) (Joe Fiveman) has child Joe Other children are (Joe) (Joe) (Joe Fiveman) has child Joe Other children are (Joe Joe) () CLIPS> Как показывают результаты запуска правил, существуют три различных способа связывания переменных ?child, $?before и $?after с фактом f — 3. В первом случае переменная $? Ьейоге связывается со значением ( ),? child— co значением Joe, а переменная $?after — со значением ( Joe Joe). Во втором случае переменная $? be f ore связывается со значением ( Joe ), переменная ?child — со значением Joe, а переменная $?аЙ1ег — со значением ( Joe). В третьем случае переменная $?be f ore связывается со значением ( Хое 7ое), переменная ? child — со значением Joe, а переменная $? аЙ1ег — со значением (). Реализация стека (defrule push-value ?push- value <- (push-value ?value) ?stack <- (stack $?rest) — > Стек это упорядоченная структура данных, обеспечивающая добавление и удаление элементов. Элементы добавляются и удаляются только на одном из "концов" стека. Водной операции может осуществляться добавление нового элемента к стеку (элемент задвигается в стека в другой операции последний добавленный элемент удаляется (выталкивается) из стека. В стеке первый добавленный элемент становится последним удаляемым элементом, а последний добавленный элемент первым удаляемым элементом. В качестве наглядной аналогии для понятия стека может служить стопка подносов в кафетерии. Новые подносы добавляются (задвигаются) поверх подносов, уже находящихся в стеке. Последние подносы, наложенные поверх имеющихся в стопке подносов, становятся первыми снимаемыми (выталкиваемыми) подносами. С помощью многозначных переменных можно относительно легко реализовать стек, который способен выполнять операции задвинуть) и рор (вытолкнуть. Прежде всего необходимо предусмотреть упорядоченный факт stack, который содержит список элементов. Ниже приведено правило, с помощью которого можно задвинуть значение в факт stack. 7.24. Многозначные подстановочные символы и переменные 613 (retract ?push-value ?stack) (assert (stack ?value $?rest)) (printout t "Pushing value " ?value crlf)) А для реализации действия по выталкиванию необходимо предусмотреть два правила: относящееся к пустому стеку и относящееся к стеку, в котором имеется значение, предназначенное для выталкивания (defrule pop-value-valid ?pop-value <- (pop-value) ?stack <- (stack ?value $? rest) — > (retract ?pop-value ?stack) (assert (stack $?rest)) (printout t "Popping value " ?value crlf)) (defrule pop-value-invalid ?pop-value <- (pop-value) (stack) — > (retract ?pop-value) (printout t "Popping from empty stack" crlf)) Эти правила можно легко модифицировать таким образом, чтобы сих помощью задвигать и выталкивать значения в именованных стеках. Например, шаблоны ?push-value <- (push-value ?value) ?stack <- (stack $? rest) можно заменить на такие шаблоны, в которых переменная представляет имя стека ?push-value <- (push-value ? name ?value) ?stack <- (stack ?name $?rest) Еще один вариант программы для мира блоков (deffacts initial-state (stack А В С) Задачу составления плана для мира блоков можно решить иначе, намного проще, с использованием многозначных подстановочных символов и переменных. Для этого, как показано ниже, применяется возможность представить каждый столбик блоков с помощью единственного факта. Операции по перемещению блоков аналогичны операциям, применяемым в примере реализации операций push и pop: 614 Глава 7. Введение в CLIPS (stack D Е F) (goal (move СЕ) Пустой факт stack включен для того, чтобы исключить возможность добавления этого факта в дальнейшем; например, это может произойти, если в столбце имеется только один блока этот блок перемещается на другой. Ниже приведены правила программы для мира блоков, в которой используются многозначные переменные. (defrule move-directly ? goal <- (goal (move ?block1) (on-top-of ?block2)) ?stack-1 <- (stack ?blockl $?rest1) ?stack-2 <- (stack ?block2 $?rest2) — > (retract ? |