Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
74
Добавлен:
22.05.2015
Размер:
155.69 Кб
Скачать

Упорядоченные факты

Факты с именем отношения, имеющие соответствующую конструкцию deftemplate, называются фактами с конструкцией deftemplate. С другой стороны, факты с именем отношения, не имеющие соответствующей конструк­ции deftemplate, называются упорядоченными фактами. Под этим подра­зумевается, что упорядоченные факты имеют единственный многозначный слот, используемый для хранения всех значений, следующих за именем отношения. В действительности при обнаружении интерпретатором CLIPS каждого упорядо­ченного факта автоматически создается подразумеваемая конструкция deftem­plate для этого факта (в отличие от явной конструкции deftemplate, создаваемой с применением определения deftemplate). Любой упорядоченный факт имеет только один слот, поэтому при определении такого факта имя слота не требуется. Например, с помощью следующего факта может быть представлен список чисел:

(number-list 7 9 3 4 20)

По существу это определение эквивалентно определению такой конструкции deftemplate:

(deftemplate number-list (multislot values)) и последующему заданию факта таким образом:

(number-list (values 7 9 3 4 20))

Вообще говоря, при любой возможности следует использовать факты с кон­струкцией deftemplate, поскольку благодаря наличию имен слотов факты ста­новятся более пригодными для чтения, а работа с ними облегчается. Тем не менее можно назвать два случая, в которых полезны и упорядоченные факты. Во-пер­вых, факты, состоящие только из имени отношения, могут применяться в качестве флагов и выглядят одинаково, независимо от того, была для них определе­на конструкция deftemplate или нет. Например, следующий упорядоченный факт может использоваться в качестве флажка для указания на то, что все заказы обработаны:

(all-orders-processed)

Во-вторых, для факта, содержащего единственный слот, имя слота обычно становится синонимом имени отношения. Например, следующие факты:

(time 8:45)

(food-groups meat dairy bread fruits-and-vegetables)

несут в себе не меньше смысла, чем такие факты:

(time (value 8:45))

(food-groups (values meat dairy bread fruits-and-vegetables))

Все факты, известные системе CLIPS, группируются и сохраняются в списке фактов. Этот список фактов позволяет добавлять и удалять факты, представляю­щие информацию. Новые факты могут быть добавлены к списку фактов с исполь­зованием команды assert. Команда assert имеет следующий синтаксис:

(assert <fact>+)

В качестве примера воспользуемся конструкцией deftemplate с именем person для описания некоторых людей с помощью фактов. Информацию о че­ловеке с именем John Q. Public можно добавить к списку фактов с помощью следующих команд:

CLIPS> (deftemplate person

(slot name)

(slot age)

(slot eye-color)

(slot hair-color))

CLIPS>(assert (person (name "John Q. Public")

(age 23)

(eye-color blue)

(hair-color black)))

<Fact-0>

CLIPS>

Обратите внимание на то, что команда assert возвращает значение, <Fact-0>. Для отображения фактов, находящихся в списке фактов, можно воспользовать­ся командой facts. Основной синтаксис команды facts является таковым:

(facts)

А ниже приведен пример применения этой команды.

CLIPS> (facts)

f-0 (person (name "John Q. Public") (age 23) (eye-color blue) (hair-color black))

For a total of 1 fact.

CLIPS>

Терм "f-0" представляет собой идентификатор факта, присвоенный этому факту системой CLIPS. Каждому факту, вставляемому в список фактов, присва­ивается уникальный идентификатор факта, начинающийся с буквы f и заканчи­вающийся целым числом, которое называется индексом факта. Индекс факта 0 был показан также в возвращаемом значении <Fact-0> показанной выше коман­ды assert. При обычных обстоятельствах система CLIPS не допускает ввод дублирующихся фактов. Поэтому попытка поместить в список фактов второй факт "John Q. Public" с идентичными значениями слотов не приведет к зна­чимому результату. Но, безусловно, к списку фактов можно легко добавлять дру­гие факты, не являющиеся дубликатами существующих фактов, например, как показано ниже.

CLIPS> (assert (person (name "Jane Q. Public") (age 36)

(eye-color green) (hair-color red)))

<Fact-l>

CLIPS> (facts)

f-0 (person (name "John Q. Public") (age 23) (eye-color blue) (hair-color black))

f-1 (person (name "Jane Q. Public") (age 36) (eye-color green) (hair-color red))

For a total of 2 facts.

CLIPS>

Как показывает синтаксис команды assert, с помощью единственной коман­ды assert можно ввести в систему несколько фактов одновременно. Например, следующая команда добавляет в список фактов сразу два факта:

(assert (person (name "John Q. Public")

(age 23)

(eye-color blue)

(hair-color black))

(person (name "Jane Q. Public")

(age 36)

(eye-color green)

(hair-color red)))

Важно помнить, что идентификаторы фактов в списке фактов не обязательно должны быть последовательными. Кроме того, факты можно не только добавлять к списку фактов, но и удалять из этого списка с помощью определенного способа. После удаления фактов из списка фактов идентификаторы удаленных фактов ста­новятся пропущенными в списке фактов, поэтому в ходе выполнения программы CLIPS может быть нарушена строгая последовательность индексов фактов.

Количество фактов, содержащихся в списке фактов, может стать весьма зна­чительным, поэтому часто желательно иметь возможность рассматривать только часть списка фактов. Такая возможность обеспечивается с помощью задания до­полнительных параметров команды facts. Полный синтаксис команды facts приведен ниже:

(facts [<start> [<end> [<maximum>]]])

В этой команде в качестве параметров <start>, <end> и <maximum> при­меняются положительные целые числа. Следует отметить, что синтаксис команды facts допускает использование от нуля до трех параметров. Если параметры не заданы, отображаются все факты. Если задан параметр <start>, то отображают­ся все факты с индексами фактов, большими или равными значению <start>. Если заданы параметры <start> и <end>, отображаются все факты с индексами фактов, большими или равными значению <start> и меньшими или равными значению <end>. Наконец, если наряду с параметрами <start> и <end> за­дан параметр <maximum>, то отображается количество фактов, не превышающее значение <maximum>.

Еще раз отметим, что существует возможность не только добавлять, но и уда­лять факты из списка фактов. Удаление фактов из списка фактов называется из­влечением и выполняется с помощью команды retract. Команда retract имеет следующий синтаксис:

(retract <fact-index>+)

В качестве параметров команды retract должны быть указаны индексы фактов, относящиеся к одному или нескольким фактам. Например, информацию о человеке по имени John Q. Public можно удалить из списка фактов с по­мощью такой команды:

(retract 0)

Аналогичным образом, следующая команда позволяет извлечь из списка фак­тов тот факт, который относится к Jane Q. Public:

(retract 1)

Попытка извлечь несуществующий факт приводит к получению следующе­го сообщения об ошибке (в этом сообщении ключ [PRNTUTIL1] представляет собой ключ для поиска описания данного сообщения об ошибке в справочном руководстве CLIPS Reference Manual):

[PRNTUTIL1] Unable to find fact <fact-identifier>.

В качестве примера можно указать такой фрагмент диалога системы: CLIPS> (retract 1)

CLIPS> (retract 1)

[PRNTUTIL1] Unable to find fact f-1.

CLIPS>

Единственная команда retract может использоваться для одновременного извлечения нескольких фактов. Например, следующая команда извлекает факты f-0 и f-1:

(retract 0 1)

Значения слотов фактов с конструкцией deftemplate могут модифициро­ваться с помощью команды modify. Синтаксис команды modify является тако­вым:

(modify <fact-index> <slot-modifier>+)

В этой команде параметр <slot-modifier> имеет следующий вид: (<slot-name> <slot-value>)

Например, после наступления очередного дня рождения лица по имени John Q. Public можно изменить его возраст с 23 на 24 с помощью такой команды modify:

CLIPS> (modify 0 (age 24))

<Fact-2>

CLIPS> (facts)

f-2 (person (name "John Q. Public") (age 24) (eye-color blue) (hair-color black))

For a total of 1 fact.

CLIPS>

Команда modify действует по принципу извлечения первоначального факта и последующего добавления нового факта после модификации указанных значе­ний слотов. В связи с этим для модифицированного факта вырабатывается новый индекс факта.

Команда duplicate действует по такому же принципу, за исключением того, что извлечение первоначального факта не происходит. Таким образом, если най­дется давно пропавший брат-близнец Джона, Джек, то информацию о нем можно будет добавить к списку фактов, продублировав факт с информацией о Джоне и изменив значение слота name, как показано ниже.

CLIPS> (duplicate 2 (name "Jack S. Public"))

<Fact-3>

CLIPS> (facts)

f-2 (person (name "John Q. Public") (age 24) (eye-color blue) (hair-color black))

f-3 (person (name "Jack S. Public") (age 24) (eye-color blue) (hair-color black))

For a total of 2 facts.

CLIPS>

Команды modify и duplicate не могут использоваться для работы с упо­рядоченными фактами.

Команда watch является полезным средством отладки программ. Команда watch имеет такой синтаксис:

(watch <watch-item>)

В этом определении <watch-item> обозначает один из символов facts, rules, activations, statistics, compilations, focus, deffunctions, globals, generic-functions, methods, instances, slots, messa­ges, message-handlers или all.

Отслеживание этих элементов может осуществляться в любых комбинациях для получения необходимого объема отладочной информации. Команда watch может быть вызвана на выполнение несколько раз для отслеживания больше чем одного аспекта функционирования системы CLIPS. Чтобы разрешить отслежива­ние с помощью команды watch всех аспектов функционирования системы CLIPS, можно применить ключевое слово all. По умолчанию сразу после запуска систе­мы CLIPS отслеживаются действия по компиляции, compilations, а остальные элементы команды watch не отслеживаются.

Если осуществляется отслеживание фактов с помощью символа facts, си­стема CLIPS автоматически выводит сообщение, указывающее на то, что в спис­ке фактов произошло некоторое обновление, при выполнении каждой операции вставки или удаления фактов. Применение этой команды отладки иллюстрируется в следующем командном диалоге:

CLIPS> (facts 3 3)

f-3 (person (name "Jack S. Public") (age 24) (eye-color blue) (hair-color black))

For a total of 1 fact. clips> (watch facts)

CLIPS> (modify 3 (age 25))

<== f-3 (person (name "Jack S. Public") (age 24) (eye-color blue) (hair-color black))

==> f-4 (person (name "Jack S. Public") (age 25) (eye-color blue) (hair-color black))

<Fact-4>

CLIPS>

Последовательность знаков <== указывает, что происходит извлечение факта, а последовательность знаков ==> указывает, что происходит добавление факта.

Существует возможность обеспечить отслеживание только конкретных фак­тов, указав одно или несколько имен конструкций deftemplate в конце коман­ды watch. Например, выполнение команды (watch facts person) приводит к тому, что сообщения, касающиеся фактов, отображаются только применительно к факту person.

Отображение результатов, предусмотренных командой watch, можно отме­нить с использованием соответствующей команды unwatch. Команда unwatch имеет такой синтаксис: (unwatch <watch-item>)

Часто удобно иметь возможность автоматически вводить множество фактов, а не набирать похожие друг на друга команды в режиме работы верхнего уровня. Это особенно относится к тем фактам, которые заведомо являются истинными еще до выполнения программы (например, начальные знания). Еще одна ситуа­ция, в которой удобно автоматически вводить группу фактов, относится к прогону тестовых наборов для отладки программы. Группы фактов, представляющих на­чальные знания, можно определить с помощью конструкции deffacts. Например, ниже приведен оператор deffacts, предоставляющий начальную информацию о некоторых лицах, которые уже упоминались в данной главе.

(deffacts people "Some people we know"

(person (name "John Q. Public")

(age 24)

(eye-color blue)

(hair-color black))

(person (name "Jack S. Public")

(age 24)

(eye-color blue)

(hair-color black))

(person (name "Jane Q. Public")

(age 36)

(eye-color green)

(hair-color red)))

Конструкция deffacts имеет следующий общий формат:

(deffacts <deffacts name> [<optional comment>] <facts>*)

Вслед за ключевым словом deffacts находится обязательное имя этой кон­струкции deffacts. В качестве имени может использоваться любой допустимый символ. В данном случае для конструкции выбрано имя people. За именем сле­дует необязательный комментарий в двойных кавычках. Как и необязательный комментарии правила, этот комментарий сохраняется в определении конструк­ции deffacts после загрузки соответствующего определения системой CLIPS. Вслед за именем или комментарием находятся факты, которые вводятся в список фактов с помощью оператора deffacts.

Факты, заданные в операторе deffacts, вводятся с помощью команды reset языка CLIPS. Команда reset удаляет все факты из списка фактов, а затем вво­дит факты из существующего оператора deffacts. Синтаксис команды resetявляется таковым:

(reset)

Предположим, что введена конструкция deffactsc именем people (после конструкции deftemplate с именем person); в таком случае формируется следующий диалог, показывающий, как происходит ввод фактов в список фактов с помощью команды reset:

CLIPS> (unwatch facts)

CLIPS> (reset)

CLIPS> (facts)

f-0 (initial-fact)

f-1 (person (name "John Q. Public") (age 24) (eye-color blue) (hair-color black))

f-2 (person (name "Jack S. Public") (age 24) (eye-color blue) (hair-color black))

f-3 (person (name "Jane Q. Public") (age 36) (eye-color green) (hair-color red))

For a total of 4 facts.

CLIPS>

В этом выводе показаны факты из оператора deffacts и новый факт, выра­ботанный командой reset, который имеет имя initial-fact. После запуска система CLIPS автоматически определяет следующие две конструкции:

(deftemplate initial-fact)

(deffacts initial-fact (initial-fact))

Таким образом, даже если в программе не определены какие-либо операторы deffacts, команда reset осуществляет ввод факта (initial-fact). Факт initial-fact всегда имеет идентификатор факта f-0. Польза от применения факта (initial-fact) заключается в том, что с него начинается выполнение программы (как описано в следующем разделе).