« А. П. Частиков Т. А. Гаврилова Д. Л.Белов РАЗРАБОТКА ЭКСПЕРТНЫХ СИСТЕМ. СРЕДА CLIPS Санкт-Петербург «БХВ-Петербург» 2003 ...»
Основная разница между слотами объекта и неупорядоченного факта заключается в возможности наследования. Наследование позволяет использовать в классе некоторые свойства и поведение, определенные в другом классе. COOL (объектно-ориентированная часть языка CLIPS) поддерживает множественное наследование, при котором класс может наследовать слоты и обработчики сообщений непосредственно от нескольких классов.
Инициализация объектов
Конструктор definstances позволяет создавать набор объектов, добавляющихся в базу знаний CLIPS при каждой очистке системы. При выполнении команды reset среда CLIPS очищается, а затем в список объектов добавляются все объекты, заданные конструкторами def instances. CLIPS содержит один предопределенный системный конструктор definstances, который вызывает добавление в систему объекта initial-object. К более подробному описанию особенностей создания и использования объектов мы вернемся в гл. 11.
4.2.3. Глобальные переменные
Конструктор defglobal предназначен для определения глобальных переменных. Доступ к такой переменной можно получить из любого места среды CLIPS, а значения, которые они содержат, не зависят ни от каких других конструкций языка. В отличие от этого, некоторые конструкторы (например, defruie или deffunction) позволяют создавать локальные переменные. Эти локальные переменные доступны только внутри тела соответствующего правила или функции. Глобальные переменные CLIPS подобны глобальным переменным, встречающимся в таких традиционных процедурных языках, как С или Ada. Однако, в отличие от них, глобальные переменные CLIPS являются слабо типизированными. Они способны хранить значение любого типа.
4.3. Представление знаний
CLIPS поддерживает как эвристическую, так и процедурную парадигму представления знаний. Обе эти парадигмы описаны в данном разделе. Объектно-ориентированное программирование, комбинирующее обе эти парадигмы, описано в разд. 4.4.
4.3.1. Эвристические знания
Одним из основных методов представления знаний в CLIPS являются правила. Правила используются для представления эвристик или эмпирических правил, определяющих действия, которые необходимо выполнить в случае возникновения некоторой ситуации. Разработчик экспертной системы создает набор правил, которые, работая вместе, решают поставленную задачу. Правила состоят из предпосылок и следствия. Предпосылки называются также ЕСЛИ-частью правила или LHS правила (left-hand side). Следствие называются ТО-частью правила или RHS правила (right-hand side).
Предпосылки правила представляют собой набор условий (или условных элементов), которые должны удовлетвориться, для того чтобы правило выполнилось. Предпосылки правил удовлетворяются в зависимости от наличия или отсутствия некоторых заданных фактов в списке фактов или некоторых созданных объектов, являющихся экземплярами классов, определенных пользователем. Один из наиболее распространенных типов условных выражений в CLIPS — образцы (patterns). Образцы состоят из набора ограничений, которые используются для определения того, удовлетворяет ли некоторый факт или объект условному элементу. Другими словами, образец задает некоторую маску для фактов или объектов. Процесс сопоставления образцов фактам или объектам называется сопоставлением образцов (pattern-matching). CLIPS предоставляет механизм, называемый механизмом логического вывода (inference engine), который автоматически сопоставляет образцы с текущим списком фактов и определенными объектами и ищет правила, которые применимы в настоящий момент.
Следствие правила представляется набором некоторых действий, которые нужно выполнить, в случае если правило применимо к текущей ситуации. Таким образом, действия, заданные в следствии правила, выполняются по команде механизма логического вывода, если все предпосылки правила удовлетворены. В случае, если в данный момент применимо более одного правила, механизм логического вывода использует текущую стратегию разрешения конфликтов (conflict resolution strategy), которая определяет, какое именно правило будет выполнено. После этого CLIPS выполняет действия, описанные вследствие выбранного правила (которые могут оказать влияние на список применимых правил), и приступает к выбору следующего правила. Этот процесс продолжается до тех пор, пока список применимых правил не опустеет.
В большинстве случаев правила CLIPS можно представить в виде операторов if-then, используемых в процедурных языках программирования, например, таких как Ada или С. Однако условные выражения if-then в процедурных языках проверяются только тогда, когда поток управления программы непосредственно попадает на данное выражение путем последовательного перебора выражений и операторов, составляющих программу. В CLIPS, в отличие от этого, механизм логического вывода создает и постоянно модифицирует список правил, условия которых в данный момент удовлетворены. Эти правила запускаются на выполнение механизмом логического вывода. С этой стороны правила похожи на обработчики сообщений, присутствующие в таких языках, как, например, Ada или Smalltalk.
4.3.2. Процедурные знания
Помимо эвристической, CLIPS поддерживает и процедурную парадигму представления знаний, используемую в большинстве языков программирования. Конструкторы deffunction и defgeneric позволяют пользователю определять новые выполняемые конструкции непосредственно в среде CLIPS, возвращающие некоторые значения или выполняющие какие-то полезные действия. Вызов этих новых функций ничем не отличается от вызова встроенных функций CLIPS. Обработчики сообщений позволяют пользователю определять поведение объектов, с помощью задания той или иной реакции на сообщения. Функции, родовые функции и обработчики сообщений представляют собой отрезки кода, заданного пользователем и выполняемого, в случае необходимости, интерпретатором CLIPS. Кроме того, механизм модулей (конструктор defmodule, см. гл. 12) позволяет разбивать базу знаний CLIPS на отдельные смысловые части.
Функции
Конструктор deffunction позволяет создавать новые функции непосредственно в CLIPS. Более ранние версии CLIPS позволяли использовать только внешние пользовательские функции, написанные на каком-нибудь языке программирования (чаще всего Си) и присоединенные к среде CLIPS.
Тело функции, определенной с помощью конструктора deffunction, представляет собой последовательность действий, подобную используемой в правой части правил. Заданные пользователем действия выполняются при вызове соответствующей функции. Значение, возвращаемое функцией, является результатом вычисления последнего действия. Подробно тема функций освящена в гл. 7.
Родовые функции
Родовые функции, так же как и обычные функции, могут быть созданы непосредственно в CLIPS. Способ вызова таких функций также ничем не отличается от способа вызова обычных функций. Однако родовые функции гораздо мощнее обычных, т. к. они способны перегружаться. Благодаря механизму перегрузки родовая функция может выполнять различные действия в зависимости от типа и числа аргументов. Обычно родовая функция состоит из нескольких компонентов, называемых методами. Каждый метод содержит различный набор аргументов родовой функции.
Например, можно перегрузить системную функцию + (арифметическое сложение) для выполнения операции конкатенации двух строк. Однако после этого функция + все еще сможет выполнять арифметическое сложение. В данном примере у родовой функции + существует два метода: первый метод явно определен пользователем для конкатенации двух строк, второй представляет собой неявный вызов стандартной функции, выполняющей арифметическое сложение. Значение, возвращенное родовой функцией, является значением, полученным в результате вычисления последнего действия в применяемом методе.
Обработчики сообщений
Как уже упоминалось, объект CLIPS состоит из двух основных частей — свойств объекта и его поведения. Свойства объектов определяются в терминах слотов. Поведение объекта обуславливается обработчиками сообщений, которые являются присоединенной к классу последовательностью действий с заданным именем. Любые манипуляции с объектом можно выполнить только с помощью сообщений. Например, в случае уже упоминавшегося объекта Rolls-Royce, являющегося экземпляром пользовательского класса car, для того чтобы запустить двигатель, пользователь должен послать объекту сообщение start-engine с помощью функции send. To, каким образом объект Rolls-Royce прореагирует на это сообщение, зависит от определения обработчика сообщения start-engine, связанного с классом car. Назначение обработчиков сообщений в принципе эквивалентно назначению любой функции — возвращение результата или выполнение неких полезных действий. Более подробно тема объектов раскрывается в гл. 11.
Модули
Модули позволяют разбивать базу знаний на отдельные смысловые части. Каждый вызываемый конструктор помещается в определенный модуль. Программист имеет возможность контролировать возможности доступа и видимость конструкторов в тех или иных модулях. Кроме того, для модулей можно устанавливать видимость определенных фактов или объектов. Модули можно использовать для контроля или изменения потока выполнения правил. Подробное описание модулей приведено в гл. 12.
4.4. Объектно-ориентированные возможности CLIPS
Данный раздел дает краткий обзор элементов языка CLIPS Object-Oriented Language (COOL) — встроенного языка CLIPS, предоставляющего объектно-ориентированные возможности.
4.4.1. Отличия COOL от других объектно-ориентированных языков
В так называемых "чистых" объектно-ориентированных языках абсолютно все программные элементы являются объектами, и любые действия над ними выполняются посредством посылки сообщений. В CLIPS объектами являются только объекты классов, определенных пользователем, и объекты, представляющие данные примитивных типов CLIPS. С объектами, представляющими данные примитивных типов, можно манипулировать с помощью сообщений, а для объектов классов, определенных пользователем, это является единственно возможным способом работы с объектом. Например, в "чистых" объектно-ориентированных языках для сложения двух чисел первому из них передается сообщение add и в качестве аргумента передается второе. В CLIPS для этого достаточно просто вызвать функцию + и в качестве аргументов передать ей два числа. Однако вы можете определить соответствующий обработчик сообщения add для класса number и работать с числами в стиле "чистых" систем ООП.
Работа со всеми программными элементами CLIPS, не являющимися объектами, выполняется не в объектно-ориентированном стиле, а с помощью вызовов соответствующих функций. Например, для вывода на экран определения правила используется функция ppdefrule, которой нужное правило передается в качестве параметра, а не посылается сообщение print, так как правило не является объектом.
4.4.2. Основные возможности ООП
Любая объектно-ориентированная система должна обладать следующими пятью характеристиками: абстрактностью, инкапсуляцией, наследованием, полиморфизмом и динамическим связыванием. Абстракция — это способ представления данных на определенном уровне некоторой конкретной проблемной области. Инкапсуляция — это процесс, позволяющий скрывать детали реализации объекта с помощью некоторого определенного для этого класса внешнего интерфейса. Наследование позволяет определять классы, использующие определения других классов и обладающие всеми их и некоторыми своими свойствами, если это необходимо. Полиморфизм — свойство, благодаря которому различные объекты по-разному реагируют на одни и те же сообщения. Динамическое связывание является возможностью выбирать определенный обработчик сообщения объекта во время выполнения программы. Рассмотрим теперь, как CLIPS реализует все эти основные свойства системы ООП.
Создание нового класса реализует возможность абстрактного представления нового типа данных. Слоты и обработчики сообщений этого класса определяют свойства и поведение целой группы объектов, принадлежащих этому классу.
Инкапсуляция реализуется в CLIPS требованием обязательно использовать сообщения при работе с объектами определенных пользователем классов. Обработчики сообщений класса представляют собой доступный пользователю интерфейс, скрывающий реализацию класса.
COOL поддерживает множественное наследование. Это означает, что некоторый класс может обладать всеми свойствами указанного одного или более суперкласса. Для установления линейного порядка наследования свойств классов при множественном наследовании COOL использует список предшествования классов (class precedence list), построенный с использованием иерархии наследования. Объект, представляющий собой экземпляр нового класса, наследует все свойства (слоты) и поведение (обработчики сообщений) каждого класса из списка предшествования классов. Слово "предшествование" обозначает, что свойства и поведение класса, находящегося ближе к началу списка, переопределяют конфликтующие определения ранее встретившихся классов.
Различные COOL-объекты могут реагировать на одно и то же сообщение совершенно по-разному. Это реализует свойство полиморфизма. На практике это выполняется присоединением к разным классам обработчиков одного и того же сообщения, но с разными последовательностями выполняемых действий.
CLIPS также поддерживает возможность динамического связывания, реализуемую с помощью функции send, предназначенной для посылки сообщений объекту. Вызов этой функции осуществляется именно в процессе выполнения программы, таким образом, определение обработчика выполняющегося в тот или иной момент также происходит в процессе выполнения программы. Например, функция send может получать в качестве параметра переменную, которая в разные моменты времени ссылается на различные объекты, при этом могут вызываться совершенно разные обработчики. Подробно процесс определения нужного обработчика описан в гл. 11.
4.4.3. Запросы и наборы объектов
В дополнение к возможности использовать объекты в процессе сопоставления образцов правил, COOL поддерживает гибкую систему запросов, позволяющую использовать заданные пользователем критерии для выборки некоторого набора объектов и выполнения над ним определенных действий. Запросы позволяют объединять в наборы объекты самых разных классов. Запросы можно использовать, например, для проверки существования того или иного набора объектов, выполнения действий над набором или сохранения ссылки на набор для последующего использования. Подробное описание этой возможности COOL с примерами использования приведено в гл. 11.
ЧАСТЬ III.Основные конструкции CLIPS.
Глава 5. Факты.
Глава 6. Правила.
Глава 7. Глобальные переменные.
Глава 8. Функции.
Глава 9. Разработка экспертной системы AutoExpert.
ГЛАВА 5. Факты.
Для функционирования любой экспертной системы критически важным является наличие базы знаний. Об этом говорит даже тот факт, что в последнее время все чаще термин "система, основанная на знаниях" (knowledge-base system) употребляется в качестве синонима термина "экспертная система". Как правило, в любой экспертной системе знания представляются фактами и правилами, заданными на некотором языке описания знаний. CLIPS не является исключением и предоставляет возможности для приобретения, хранения и обработки фактов и правил. Данная глава посвящена способам работы с фактами в системе CLIPS. Работа с правилами будет описана в следующей главе.
5.1. Факты в CLIPS
Факты — одна из основных форм представления данных в CLIPS (существует также возможность представления данных в виде объектов и глобальных переменных, но об этом речь пойдет позже). Каждый факт представляет собой определенный набор данных, сохраняемый в текущем списке фактов — рабочей памяти системы. Список фактов представляет собой универсальное хранилище фактов и является частью базы знаний. Объем списка фактов ограничен только памятью вашего компьютера. Список фактов хранится в оперативной памяти компьютера, но CLIPS предоставляет возможность сохранять текущий список в файл и загружать список из ранее сохраненного файла.
В системе CLIPS фактом является список неделимых (или атомарных) значений примитивных типов данных. CLIPS поддерживает два типа фактов -упорядоченные факты (ordered facts) и неупорядоченные факты или шаблоны (non-ordered facts или template facts). Ссылаться на данные, содержащиеся в факте, можно либо используя строго заданную позицию значения в списке данных для упорядоченных фактов, либо указывая имя значения для шаблонов.
Факты можно добавлять, удалять, изменять и дублировать, вводя соответствующие команды с клавиатуры, либо из программы. Все соответствующие команды будут описаны в данной главе.
После добавления факта в список фактов ему присваивается целый уникальный идентификатор, называемый индексом факта (fact-index). Индекс первого факта равен нулю, в дальнейшем индекс увеличивается на единицу при добавлении каждого нового факта. CLIPS предоставляет команды, очищающие текущий список фактов или всю базу знаний, эти команды присваивают текущему значению индекса 0.
Некоторые команды, например изменения, удаления или дублирования фактов, требуют указания определенного факта. Факт можно задать либо индексом факта, либо его адресом. Адрес факта представляет собой переменную-указатель, хранящую индекс факта. Процесс создания адресов фактов будет описан ниже.
Упорядоченные факты состоят из поля, обязательно являющимся данным типа symbol и следующей за ним, возможно пустой, последовательности полей, разделенных пробелами. Ограничением факта служат круглые скобки.
Определение 5.1. Упорядоченный факт
(данное_типа_symЬо1 [поле]*)
Первое поле факта определяет так называемое отношение, или связь факта (relation). Термин "связь" означает, что данный факт принадлежит некоторому определенному конструктором или неявно объявленному шаблону. Подробней речь об этом пойдет ниже. Приведем несколько примеров фактов:
Пример 5.1 Упорядоченные факты
(duck is bird)
(schoolboys is Bob Mike)
(Nuke did report)
(altitude is 1000 feet)
Количество полей в факте не ограничено. Поля в факте могут хранить данные любого примитивного типа CLIPS, за исключением первого поля, которое обязательно должно быть типа symbol. Следующие слова зарезервированы и не могут быть использованы в качестве первого поля: test, and, or, not, declare, logical, object, exist и forall. Эти слова могут использоваться в качестве имен слотов шаблонов, хотя это не рекомендуется.
Так как упорядоченный факт для представления информации использует строго заданные позиции данных, то для доступа к ней пользователь должен знать не только какие данные сохранены в факте, но и какое поле содержит эти данные. Неупорядоченные факты (или шаблоны) предоставляют пользователю возможность задавать абстрактную структуру факта путем назначения имени каждому полю. Для создания шаблонов, которые впоследствии будут применяться для доступа к полям факта по имени, используется конструктор deftemplate. Конструктор deftemplate аналогичен определениям записей или структур в таких языках программирования, как Pascal или С.
Конструктор deftemplate задает имя шаблона и определяет последовательность из нуля или более полей неупорядоченного факта, называемых также слотами. Слот состоит из имени, заданного значением типа symbol, и следующим за ним, возможно пустого, списка полей. Как и факт, слот с обеих сторон ограничивается круглыми скобками. В отличие от упорядоченных фактов слот неупорядоченного факта может жестко определять тип своих значений. Кроме того, слоту могут быть заданы значения по умолчанию.
Замечание
Слоты не могут быть использованы в упорядоченных фактах, а в неупорядоченных фактах, в свою очередь, нельзя ссылаться на данные, используя порядок слотов.
CLIPS различает неупорядоченные факты от упорядоченных по первому полю факта. Первое поле фактов любого типа является значением типа symbol. Если это значение соответствует имени некоторого шаблона, то факт -упорядоченный. Определение неупорядоченного факта, как и упорядоченного, ограничивается круглыми скобками.
Ниже приведено несколько примеров неупорядоченных фактов:
Пример 5.2. Неупорядоченные факты
(client (name "Joe Brown") (id X9345A))
(point-mass (x-velocity 100) (y-velocity -200))
(class (teacher "Martha Jones") (#-students 30) (Room "37A")
(grocery-list (#-of-items 3) (items bread milk eggs))
Замечание
Порядок слотов в неупорядоченном факте не важен. Например, все приведенные ниже факты считаются идентичными:
(class (teacher "Martha Jones") (#-students 30) (Room "37A"))
(class (#-students 30) (teacher "Martha Jones") (Room "37A"))
(class (Room "37A") (#-students 30) (teacher "Martha Jones"))
В отличие от фактов, приведенных выше, упорядоченные факты из следующего примера не являются идентичными:
(class "Martha Jones" 30 "37А")
(class 30 "Martha Jones" "37A")
(class "37A" 30 "Martha Jones")
С неупорядоченными фактами можно выполнять те же операции, что и с упорядоченными.
Далее рассмотрим конструкторы, операции и функции, которые предоставляет CLIPS для работы с фактами.
5.2. Работа с фактами
CLIPS предоставляет довольно богатый набор возможностей для работы с фактами с помощью соответствующих конструкторов, операций и функций. Эти возможности включают создание шаблонов с помощью конструктора deftemplate, создание, изменение, удаление, поиск фактов, просмотр, сохранение и загрузку списка фактов, определение списка предопределенных фактов с помощью конструктора deffacts и многое другое.
5.2.1. Конструктор deftemplate
Для создания неупорядоченных фактов в CLIPS предусмотрен специальный конструктор deftemplate. Его использование приводит к появлению в текущей базе знаний системы информации о шаблоне факта, с помощью которого в систему в дальнейшем можно будет добавлять факты, соответствующие данному шаблону. Таким образом, конструктор deftemplate аналогичен операторам record и struct таких процедурных языков программирования как Pascal или С.
Приведем простой пример использования конструктора deftemplate:
Пример 5.3. Применение конструктора deftemplate
(deftemplate MyObject
(slot name)
(slot location)
(slot weight)
(multislot contents))
Как и все конструкторы CLIPS, конструктор deftemplate не возвращает никакого значения. При вводе данной команды в CLIPS вы должны увидеть результат, приведенный на рис. 5.1.
Рис. 5.1. Использование конструктора deftemplate
Подобная реакция среды говорит об удачном добавлении определения шаблона в систему. Для просмотра всех определенных в текущей базе знаний шаблонов можно воспользоваться командой get-deftemplate-list, речь о которой пойдет ниже, или специальным инструментом Deftemplate Manager (Менеджер шаблонов), доступным в Windows-версии среды CLIPS. Для запуска менеджера шаблонов воспользуйтесь меню Browse и выберите пункт Deftemplate Manager (рис. 5.2).
Менеджер шаблонов позволяет в отдельном окне просматривать список всех шаблонов, доступных в текущей базе знаний, удалять выбранный шаблон и отображать все его свойства (например, такие как имена и типы слотов). Внешний вид менеджера шаблонов представлен на рис. 5.3.
После выполненной нами операции в текущей базе знаний находится два шаблона, о чем сообщается в заголовке окна менеджера (Deftemplate Manager — 2 Items). Первый шаблон является предопределенным шаблоном initial-fact. Он не имеет слотов и всегда добавляется при запуске среды. Его нельзя удалить с помощью менеджера, или просмотреть его определение. Назначение и примеры использования факта initial-fact будут рассмотрены ниже. Вторым шаблоном является только что добавленный шаблон MyObject. Менеджер шаблонов позволяет вывести в главное окно среды его определение с помощью кнопки Pprint или удалить его из среды посредством кнопки Remove. На рис. 5.4 приведен результат последовательных операций вывода информации об определении шаблона и удалении его из текущей базы знаний.
Рис. 5.2. Запуск менеджера шаблонов
Рис. 5.З. Окно менеджера шаблонов
Рис. 5.4. Получение информации и удаление шаблона
Флажок Watch позволяет включать/выключать режим отображения сообщений об использовании шаблонов для каждого присутствующего в системе шаблона в главном окне среды CLIPS. Если этот режим включен, пользователь будет получать сообщения при добавлении и удалении неупорядоченных фактов, использующих данный шаблон.
В случае, если при добавлении нового шаблона с помощью конструктора deftemplate произошла ошибка, пользователь получит соответствующее предупреждение. Полный список сообщений об ошибках в системе CLIPS приведен в приложениях 2 и 3.
Переопределение уже существующего шаблона приводит к исключению предыдущего определения. Шаблон не может быть переопределен до тех пор, пока он используется (например, фактом или правилом). Шаблон может иметь любое количество простых или составных слотов. CLIPS отличает простые и составные слоты в шаблоне. Например, будет ошибкой сохранять значение составного слота в простой слот.
Рассмотрим полный синтаксис конструктора deftemplate:
Определение 5.2. Синтаксис конструктора deftemplate
(deftemplate <имя-шаблона>[<необязательные-комментарии>] [<определение-слота>*])
<определение-слота> ::= <определение-простого-слота>|<определение-составного-слота>
<определение-простого-слота> ::= (slot <имя-поля> <атрибуты-шаблона>)
<определение-составного-слота> ::= (multislot <имя-поля> <атрибуты-шаблона>)
<атрибуты-шаблона> ::= <атрибут-значение-по-умолчанию>|<атрибут-ограничения>
<атрибут-значение-по-умолчанию> ::= (default ?DERIVE I ?NONE |<Выражение>)|
(default-dynamic <Выражение>)
Заметим еще раз, что имена шаблонов и слотов должны быть значениями типа symbol, кроме того, на имена шаблонов распространяется запрет на использование некоторых слов, зарезервированных системой, перечисленных выше.
Комментарии являются необязательными и, как правило, описывают назначения шаблона. Комментарии необходимо заключать в кавычки. Кроме данного типа комментариев в конструкторе deftempiate также применимы обычные комментарии CLIPS, начинающиеся с символа ;. Отличие этих комментариев заключается в том, что комментарии, начинающиеся с символа ;, полностью игнорируются системой CLIPS, а комментарии, следующие после имени шаблона и заключенные в кавычки, сохраняются в базе знаний системы. Эти комментарии доступны при просматривании определения шаблона. Определим в среде CLIPS следующий шаблон:
Пример 5.4. Применение конструктора deftemplate
(deftemplate MyObject "Template for storage name and location"
; Slots for storage name and location
(slot name) ;slot for name of object
(slot location) ; slot for location of object
После удачного добавления шаблона в систему, с помощью менеджера шаблонов, выведите в главное окно CLIPS информацию об определении шаблона MyObject. Если перечисленные действия были выполнены без ошибок, то на экране должны появиться сообщения, идентичные показанным на рис. 5.5.
Обратите внимание, что комментарии "Template for storage name and location" сохранены в памяти системы и отображаются вместе с определением шаблона. К сожалению, текущая версия CLIPS не воспринимает символы кириллицы даже в качестве комментариев, поэтому все комментарии придется давать на английском языке.
Рис. 5.5. Использование комментариев в конструкторе deftemplate
Помимо ключевого слова slot, определяющего простой слот, допустимо также применение ключевого слова multisiot, для определения составного слота. Простой слот, или слот, предназначен для хранения единицы информации одного из примитивных типов данных CLIPS. Составной слот способен хранить список подобных единиц информации неограниченного объема. Для доступа к конкретным данным, хранящимся в составном слоте, используются специальные групповые символы и функции, примеры и правила использования которых будут приведены ниже.
При создании шаблона с помощью конструктора deftemplate каждому полю можно назначать определенные атрибуты, задающие значения по умолчанию или ограничения на значение слота. Рассмотрим эти атрибуты подробней.
<Атрибут-значение-по-умолчанию> определяет значение, которое будет использовано в случае, если при создании факта не задано конкретное значение слота. В CLIPS существует два способа определения значения по умолчанию, поэтому в конструкторе deftemplate предусмотрено два различных атрибута, задающих значения по умолчанию: default и default-dynamic.
Атрибут default определяет статическое значение по умолчанию. С его помощью задается выражение, которое вычисляется один раз при конструировании шаблона. Результат вычислений сохраняется вместе с шаблоном. Этот результат присваивается соответствующему слоту в момент объявления нового факта. В случае если в качестве значения по умолчанию используется ключевое слово ?derive, то это значение будет извлекаться из ограничений, заданных для данного слота. По умолчанию для всех слотов установлен атрибут default ?DERIVE.
В случае если в место выражения для значения по умолчанию используется ключевое слово ?none, то значение поля обязательно должно быть явно задано в момент выполнения операции добавления факта. Добавление факта без определения значений полей с атрибутом default ?none вызовет ошибку.
Атрибут default-dynamic предназначен для установки динамического значения по умолчанию. Этот атрибут определяет выражение, которое вычисляется всякий раз при добавлении факта по данному шаблону. Результат вычислений присваивается соответствующему слоту.
Простой слот может иметь только одно значение по умолчанию. У составного слота может быть определено любое количество значений по умолчанию (количество значений по умолчанию должно соответствовать количеству данных, сохраняемых в составном слоте).
Ниже приведен пример использования атрибута, устанавливающего значение по умолчанию:
Пример 5.5. Использование атрибутов значения по умолчанию
(deftemplate foo
(slot w (default ?NONE))
(slot x (default ?DERIVE))
(slot у (default (gensym*)))
(slot z (default-dynamic (gensym*))))
Синтаксис и функциональность <атрибута-ограничения> для простого и составного слота детально описаны в гл. 13. В конструкторе deftemplate поддерживается проверка статических и динамических ограничений.
Статическая проверка выполняется во время использования определения шаблона некоторой командой или конструктором. Например, для записи значений в слоты шаблона. Иначе говоря, статическая проверка выполняется до запуска программы. При несоответствии используемых значений с установленными ограничениями пользователю выводится соответствующее предупреждение об ошибке.
Ссылка на индекс факта в командах на изменение значения факта или его дублирование не связывает факт с соответствующим шаблоном явно. Это делает статическую проверку неоднозначной. Поэтому в командах, использующих индекс факта, статическая проверка не выполняется.
Статическая проверка ограничений включена по умолчанию. Эту установку среды CLIPS можно изменить с помощью функции set-static-constraint-checking.
Помимо статической, CLIPS также поддерживает динамическую проверку ограничений. Если режим динамической проверки ограничений включен, го все новые факты, созданные с использованием некоторого шаблона и имеющие определенные значения, проверяются в момент их добавления в список фактов.
В случае если нарушение заданных ограничений произойдет в момент выполнения динамической проверки в процессе выполнения программы, то выполнение программы прекращается и пользователю будет выдано соответствующее сообщение.
По умолчанию в CLIPS отключен режим динамической проверки ограничений. Эту среду установки можно изменить с помощью функции set-dynamic-constraint-checking.
Помимо описанных выше функций для изменения состояний режимов статической и динамической проверки ограничений, пользователям Windows-версии среды CLIPS доступен визуальный способ настройки этих установок. Для этого необходимо открыть диалоговое окно Execution Options, выбрав пункт Options из меню Execution. Внешний вид этого диалогового окна приведен на рис. 5.6.
Рис. 5.6. Диалоговое окно Execution Options
Для включения или выключения необходимых режимов проверки ограничений атрибутов выставите в соответствующее положение флажки Static Constraint Checking и Dynamic Constraint Checking и нажмите кнопку ОК.
Ниже приведен пример использования атрибутов ограничения типа:
Пример 5.6. Использование атрибутов ограничения
(deftemplate object
(slot name
(type SYMBOL)
(default ?DERIVE))
(slot location
(type SYMBOL)
(default ?DERIVE)))
Для полноты картины следует также упомянуть о неявно создаваемых шаблонах. При использовании факта или ссылки на упорядоченный факт (например, в правиле) CLIPS неявно создает соответствующий шаблон с одним составным слотом. Имя неявно созданного составного слота не отображается при просмотре фактов. Неявно созданным шаблоном можно манипулировать и сравнивать его с любым тождественным, определенным пользователем шаблоном, несмотря на то, что он не имеет отображаемой формы.
5.2.2. Конструктор deffacts
Помимо конструктора deftemplates, CLIPS предоставляет конструктор deffacts, также предназначенный для работы с фактами. Данный конструктор позволяет определять список фактов, которые будут автоматически добавляться всякий раз после выполнения команды reset, очищающей текущий список фактов. Факты, добавленные с помощью конструктора deffacts, могут использоваться и удаляться так же, как и любые другие факты, добавленные в базу знаний пользователем или программой, с помощью команды assert.
Определение 5.3. Синтаксис конструктора deffacts
(deffacts <имя-списка-фактов> [<необязательные-комментарии>] [<факт>*])
Добавление конструктора deffacts с именем уже существующего конструктора приведет к удалению предыдущего конструктора, даже если новый конструктор содержит ошибки. В среде CLIPS возможно наличие нескольких конструкций deffacts одновременно и любое число фактов в них (как упорядоченных, так и неупорядоченных). Факты всех созданных пользователем конструкторов deffacts будут добавлены при инициализации системы.
Все замечания по поводу использования комментариев в конструкторе deftemplate применимы и к конструктору deffacts.
В поля факта могут быть включены динамические выражения, значения которых будут вычисляться при добавлении этих фактов в текущую базу знаний CLIPS.
Пример 5.7. Использование конструктора deffacts
(deffacts startup "Refrigerator Status"
(refrigerator light on)
(refrigerator door open)
(refrigerator temp (+ 5 10 15))
Обратите внимание, что третий факт содержит выражение, в данном примере сумму трех констант, но в качестве выражения, инициализирующего значение факта, могут использоваться и более сложные выражения, например, вызовы функций CLIPS или функций, определенных пользователем.]
Проверить работу конструктора deffacts можно воспользовавшись диалогом Watch Options. Для этого выберите пункт Watch меню Execution или используйте комбинацию клавиш <Ctrl>+<W>. В диалоговом окне Watch Options включите режим просмотра изменения списка фактов, поставив галочку в поле Facts, как показано на рис. 5.7.
Рис. 5.7. Диалоговое окно Watch Options
После этого нажмите кнопку ОК и введите в CKIOS приведенный выше конструктор deffacts. Затем в меню Execution выберите пункт Reset (комбинация клавиш <Ctrl>+<E>). Если пример был набран правильно, то на экране должны появиться сообщения, аналогичные приведенным на рис. 5.8.
Рис. 5.8. Просмотр процесса добавления файлов
Так же, как и для конструкторов deftemplate, CLIPS предоставляет визуальный инструмент для манипуляции с определенными в данный момент в системе конструкторами deffacts -- Deffacts Manager (Менеджер предопределенных фактов). Для запуска Deffacts Manager в меню Browse выберите пункт Deffacts Manager. Внешний вид менеджера приведен на рис. 5.9.
Рис. 5.9. Окно менеджера предопределенных фактов
Менеджер отображает все введенные на текущий момент в систему конструкторы deffacts. В нашем случае это initial-fact, речь о котором пойдет ниже, и только что добавленный нами startup. Менеджер позволяет выводить в основное окно CLIPS информацию об определениях существующих в данный момент в системе конструкторов deffacts с помощью кнопки Pprint (кроме deffacts initial-fact) и удалять любой существующий конструктор. Пример вывода информации об определении конструктора deffacts startup приведен на рис. 5.10. Обратите внимание, что комментарии, введенные после имени конструктора, сохраняются и выводятся на экран так же, как в конструкторе deftemplate.
Рис. 5.10. Получение информации об определенном конструкторе
Во время запуска и после выполнения команды clear CLIPS автоматически конструирует следующие предопределенные шаблоны и факты:
Определение 5.4. Предопределенные шаблоны и факты
(deftemplate initial-fact)
(deffacts initial-fact
(initial-fact))
Предопределенный факт initial-fact шаблона initial-fact предоставляет удобный способ для запуска программ на языке CLIPS — правила, не имеющие условных элементов, автоматически преобразуются в правила с условием, проверяющим наличие факта initial-fact. Факт initial-fact можно обрабатывать так же, как и все остальные факты CLIPS, добавленные пользователем или программой с помощью команды assert. Пример использования факта initial-fact будет приведен в следующей главе, сразу после первого знакомства с правилами CLIPS.
5.2.3. Функция assert
Функция assert - одна из наиболее часто применимых команд в системе CLIPS. Без использования этой команды нельзя написать даже самую простую экспертную систему и запустить ее на выполнение в среде CLIPS. Функции Assert, retract и modify — три рабочие лошадки, используемые большинством правил.
Функция assert позволяет добавлять факты в список фактов текущей базы знаний. Каждым вызовом этой функции можно добавить произвольное число фактов. В случае если был включен режим просмотра изменения списка фактов (как было описано в разд. 5.2.2), то соответствующее информационное сообщение будет отображаться в окне CLIPS при добавлении каждого факта.
Определение 5.5. Синтаксис команды assert
(assert <факт>+)
При использовании команды assert необходимо помнить, что первое поле факта обязательно должно быть значением типа symbol. В случае удачного добавления фактов в базу знаний, функция возвращает адрес последнего добавленного факта. Если во время добавления некоторого факта произошла ошибка, команда прекращает свою работу и возвращает значение false.
Слотам неупорядоченного факта, значения которых не заданы, будут присвоены значения по умолчанию (см. разд. 5.2.1).
:
Пример 5.8. Использование функции assert
(clear)
(assert (color red))
(assert (color blue)
(value (+ 3 4)))
(deftemplate status
(slot temp)
(slot pressure
(default low)))
(assert (status (temp high)))
Команда clear очищает текущий список фактов (а также все определенные конструкторы, которые уже были и еще будет рассмотрены ниже). В отличие от reset, команда clear не добавляет в список фактов initial-fact. Эту команду также можно выполнить, выбрав пункт Clear CLIPS в меню Execution. При выборе данной команды на экране появляется диалоговое окно, представленное на рис. 5.11. Это окно запрашивает подтверждение пользователя на очистку текущей базы знаний.
Рис. 5.11. Подтверждение очистки среды CLIPS
В случае, если команда была набрана с клавиатуры, никакого подтверждения на выполнение этой операции система не запрашивает. Если вы недавно начали работать в среде CLIPS, то для очистки системы лучше использовать меню, т. к. потеря всех текущих данных из базы знаний может оказаться весьма болезненной.
Включите режим просмотра изменения списка фактов и наберите приведенный выше пример. После этого выполните команду (facts). Если при
Рис. 5.12. Добавление фактов
выполнении этих действий не было допущено ошибок, то вы должны получить результат, идентичный изображенному на рис. 5.12.
Обратите внимание, что при инициализации факта value использовалось выражение, а слот pressure неупорядоченного факта status получил значение по умолчанию low.
По умолчанию CLIPS не позволяет добавлять в список фактов два одинаковых факта. Например, попытка добавить два факта color red приведет к ошибке и функция assert вернет значение false. Данную установку системы можно изменить с помощью функции set-fact-duplication. Кроме того, пользователям Windows-версии CLIPS доступен еще один способ настройки. Для этого необходимо открыть диалоговое окно Execution Options, выбрав пункт Options из меню Execution, установить флажок Fact Duplication. Внешний вид этого диалогового окна приведен на рис. 5.6.
5.2.4. Функция retract
После добавления факта в базу знаний рано или поздно встанет вопрос о том, как его оттуда удалить. Для удаления фактов из текущего списка фактов в системе CLIPS предусмотрена функция retract. Каждым вызовом этой функции можно удалить произвольное число фактов. Удаление некоторого факта может стать причиной удаления других фактов, которые логически связаны с удаляемым. Кроме того, удаление факта вызывает удаления правил из плана решения текущей задачи, активированных удаляемым фактом, но об этом речь пойдет в следующих главах. В случае если был включен режим просмотра изменения списка фактов, то соответствующее информационное сообщение будет отображаться в окне CLIPS при удалении каждого факта.
Определение 5.6. Синтаксис команды retract
(retrасt <определение-факта>+ \ *)
Аргумент <определение-факта> может являться либо переменной, связанной с адресом факта с помощью правила (эта возможность будет описана в следующей главе), либо индексом факта без префикса (например, 3 для факта с индексом f-3), либо выражением, вычисляющим этот индекс (например, (+ 1 2) для факта с индексом f-3). Если в качестве аргумента функции retract использовался символ *, то из текущей базы знаний системы будут удалены все факты. Функция retract не имеет возвращаемого значения.
Для демонстрации работы функции retract воспользуемся еще одним визуальным инструментом, не описанным ранее. Он предназначен для просмотра содержимого списка фактов в реальном времени. Этот инструмент доступен только пользователям Windows-версии системы CLIPS. Для того чтобы активизировать просмотр списка фактов, поставьте флажок рядом с пунктом Facts Window меню Windows, как показано на рис. 5.13. Внешний вид инструмента просмотра списка фактов показан на том же рисунке. Сразу после запуска CLIPS этот список пуст.
Рис. 5.13. Список фактов
Включите режим просмотра изменения списка фактов с помощью диалогового окна Watch Options и добавьте в список фактов следующие факты:
Пример 5.9. Добавление фактов
(assert (а) (b) (с) (d) (e) (f))
Обратите внимание, что в окне просмотра фактов теперь отображаются все 6 добавленных фактов.
Пример 5.10. Удаление фактов
(retract 0 (+ 0 2) (+022))
Эта команда удалит все факты с четными индексами, используя индекс факта непосредственно (первый аргумент) и выражение, которое вычисляет индекс факта (второй и третий аргумент). Если перечисленные команды были выполнены правильно, то результат должен соответствовать рис. 5.14.
Рис. 5.14. Результат добавления и удаления фактов
В случае, если факт с указанным индексом не будет найден, CLIPS выдаст соответствующее сообщение об ошибке.
Выполните команду:
Пример 5.11. Удаление всех фактов
(retract *)
После выполнения данной команды список фактов будет очищен полностью и окно отображения текущего состояния списка фактов станет идентично изображенному на рис. 5.13.
Необходимо заметить, что функция retract не оказывает никакого воздействия на индекс следующих добавленных фактов, т. е. этот индекс не обнуляется. Если после удаления всех введенных фактов добавить в систему какой-нибудь факт, то он получит индекс f-б, несмотря на то, что список фактов в данный момент пуст.
5.2.5. Функция modify
Используя функции assert и retract, можно выполнять большинство необходимых для функционирования правил действий. В том числе и изменения существующего факта. Например, если в список фактов ранее был добавлен факт (temperature is low), который получил индекс 0, то изменить его значение можно, например, следующим образом:
Пример 5.12. Изменение существующего факта
(clear)
(assert (temperature is low) )
(retract 0)
(assert (temperature is high) )
Для изменения упорядоченных фактов доступен только этот способ. Для упрощения операции изменения неупорядоченных фактов CLIPS предоставляет функцию modify, которая позволяет изменять значения слотов таких фактов. Modify просто упрощает процесс изменения факта, но ее внутренняя реализация эквивалентна вызовам пар функций retract и assert. За один вызов modify позволяет изменять только один факт. В случае удачного выполнения функция возвращает новый индекс модифицированного факта. Если в процессе выполнения произошла какая-либо ошибка, то пользователю выводится соответствующее предупреждение и функция возвращает значение FALSE.
Определение 5.7. Синтаксис команды modify
(modify <определение-факта>
<новое-значение-слота>+)
Аргументом <определение-факта> может быть либо переменная, связанная с адресом факта с помощью правила, либо индекс факта без префикса (например, 3 для факта с индексом f-3). После определения факта следует список из одного или более новых значений слотов указанного шаблона. Для использования приведенного выше примера его необходимо переделать следующим образом:
Пример 5.13. Изменение существующего неупорядоченного факта
(deftemplate temperature (slot value) )
(assert (temperature (value low)) )
(modify 0 (value high) )
Если включить режим просмотра изменения списка фактов (как было описано в разд. 5.2.2) и выполнить приведенные выше команды, то полученный результат должен соответствовать рис. 5.15.
Рис. 5.15. Результат изменения существующего неупорядоченного факта
Обратите внимание на движение фактов в базе знаний CLIPS при выполнении функции modify — сначала удаляется старый факт с индексом f-o, a затем добавляется новый факт с индексом f-1, идентичный предыдущему, но с новым значением заданного слота.
Если в шаблоне заданного факта отсутствует слот, значение которого требуется изменить, CLIPS выведет соответствующее сообщение об ошибке. Если заданный факт отсутствует в списке фактов, пользователь также получит соответствующее предупреждение.
5.2.6. Функция duplicate
Помимо функции modify, в CLIPS существует еще одна очень полезная функция, упрощающая работу с фактами, — функция duplicate. Эта функция создает новый неупорядоченный факт заданного шаблона и копирует в него определенную пользователем группу полей уже существующего факта того же шаблона. По действиям, которые выполняет функция duplicate, аналогична modify, за исключением того, что она не удаляет старый факт из списка фактов. Одним вызовом функции duplicate можно создать одну копию некоторого заданного факта. Как и функция modify, duplicate, в случае удачного выполнения, возвращает индекс нового факта, а в случае неудачи — значение false.
Определение 5.8. Синтаксис команды duplicate
(duplicate <определение-факта>
<новое-значение-слота>+)
Аргумент <определение-факта> может быть либо переменной, связанной с адресом факта с помощью правила, либо индексом факта без префикса. После определения факта следует список из одного или более новых значений слотов указанного шаблона. Продемонстрируем работу данной функции на следующем примере:
Пример 5.14. Создание копии существующего неупорядоченного факта
(deftemplate car
(slot name)
(slot producer)
(slot type)
(slot max-speed))
(assert ( car
(name scorpio)
(producer ford)
(type sedan)
(max-speed 180)))
(duplicate 0
(type off-road)
(max-speed 130))
В приведенном примере определяется шаблон, описывающий свойства автомобиля, и добавляется факт — автомобиль Ford Scorpio с типом кузова седан и максимальной скоростью 180 (км/ч). После этого с помощью функции duplicate добавляется факт с информацией об еще одном автомобиле с похожими характеристиками — это внедорожник Ford Scorpio с максимальной скоростью 130 (км/ч). Duplicate просто облегчает нам жизнь, избавляя от излишнего ввода значений данных совпадающих слотов.
В случае, если добавляемый с помощью duplicate факт уже присутствует в списке фактов, будет выдана соответствующая информация об ошибке и возвращено значение false. Факт при этом добавлен не будет. Это поведение можно изменить, разрешив существование одинаковых фактов в базе знаний. Как это сделать, было описано в разд. 5.2.3.
5.2.7. Функция assert-string
Кроме функции assert, CLIPS предоставляет еще одну функцию, полезную при добавлении фактов, — assert-string. Эта функция принимает в качестве единственного аргумента символьную строку, являющуюся текстовым представлением факта (в том виде, в котором вы набираете его, например, в функции assert), и добавляет его в список фактов. Функция assert-string может работать как с упорядоченными, так и с неупорядоченными фактами. Одним вызовом функции assert-string можно добавить только один факт.
Определение 5.9. Синтаксис команды assert-string
(assert-string <строковое-выражение>)
Строковое выражение должно быть заключено в кавычки. Функция преобразует заданное строковое выражение в факт CLIPS, разделяя отдельные слова на поля, с учетом определенных в системе на текущий момент шаблонов. Если в строке необходимо записать внутреннее строковое выражение, представляющее, скажем, некоторое поле, то для включения в строковое выражение символа кавычек используется обратная косая черта (backslash). Например, факт (book-name "clips user Guide") можно добавить следующим образом:
Пример 5.15. Использование кавычек внутри строки
(assert-string "(book-name V'CLIPS User Guide\")")
Для добавления содержащегося в поле символа обратной косой черты используйте ее дважды. Если обратная косая должна содержаться внутри подстроки, ее необходимо использовать четыре раза. Например, для помещения в текущий список факта (a\b "c\d") необходимо вызвать функцию assert-string со следующим строковым аргументом:
Пример 5.16. Использование обратной косой черты
(assert-string "(a\\b \"c\\\\d\")")
Если добавления факта прошло удачно, функция возвращает индекс только что добавленного факта, в противном случае функция возвращает сообщение об ошибке и значение false. Функция assert-string не позволяет добавлять факт в случае, если такой факт уже присутствует в базе знаний (если вы еще не включили возможность присутствия одинаковых фактов).
5.2.8. Функция fact-existp
В этом разделе рассмотрим очень простую, но чрезвычайно важную функцию fact-existp. Эта функция определяет, присутствует ли в данный момент факт, заданный индексом или переменной указателем, в базе знаний системы. В случае если факт присутствует в списке фактов, функция возвращает значение true, иначе — false.
Определение 5.10. Синтаксис команды fact-existp
( fact-existp <определение-факта>)
Обычно эта функция применяется в правилах, описанных в следующей главе. Приведем простой пример использования данной функции:
Пример 5.17. Использование функции fact-existp
(clear)
(assert-string "(a\\b \"c\\\\d\")")
(fact-existp 0)
(retract 0)
(fact-existp 0)
Замечание
He забудьте выполнить команду clear, чтобы добавленный факт имел нулевой индекс. После первого вызова функция fact-exist вернет значение true, а после удаления факта с индексом 0 — false.
5.2.9. Функции для работы с неупорядоченными фактами
Для работы с неупорядоченными фактами в CLIPS предусмотрен целый ряд специальных функций. К ним относятся: fact-relation, fact-slot-names и fact-slot-value. Рассмотрим эти функции по порядку.
Функция fact-relation позволяет получить связь (relation) существующего факта с шаблоном. Связь факта с шаблоном, определенным с помощью конструктора deftemplate или неявно созданным шаблоном, определяется по первому полю факта. Это поле всегда является простым полем и используется CLIPS в качестве имени шаблона, с которым связан факт. Таким образом, функция fact-relation просто возвращает первое поле факта, или значение false, если указанный факт не найден.
Определение 5.11. Синтаксис команды fact-relation
(fact-relation <определение-факта>)
В качестве определения факта, как и в описанных выше функциях, нужно использовать или переменную указатель, содержащую адрес факта, или индекс факта.
Пример 5.18. Использование функции fact-relation
(clear)
(assert (car Ford))
(fact-relation 0)
(retract 0)
(fact-relation 0)
В первом случае функция fact-relation вернет значение car, а во втором —FALSE.
Для получения имен всех слотов заданного факта в CLIPS предназначена функция fact-slot-names.
Определение 5.12. Синтаксис команды fact-slot-names
(fact- slot-names <определение-факта>)
Данная функция возвращает список имен слотов в составном поле. Для упорядоченных фактов функция возвращает значение implied (подразумеваемый), т. к., если вы помните, CLIPS представляет упорядоченные факты как неявно заданные неупорядоченные с одним составным слотом. В случае если заданный факт не найден, функция возвращает значение false.
Пример 5.19. Использование функции fact-slot-names
(clear)
(deftemplate car
(slot name)
(slot producer)
(slot type)
(slot max-speed))
(assert ( car
(name scorpio)
(producer ford)
(type sedan)
(max-speed 180)))
(fact-slot-names 0)
Если приведенный пример был набран без ошибок, то функция fact-slot-names вернет значение (name producer type max-speed).
Последней из рассмотренных в данной главе функций для работы с неупорядоченными фактами будет функция fact-slot-value.
Определение 5.13. Синтаксис команды fact-slot-value
(fact-slot-value <определение-факта> <имя-слота >)
Данная функция позволяет получать значения слота некоторого заданного факта. Если факт является упорядоченным, то для получения значения неявно определенного составного слота используется значение implied. В случае если указанный факт не существует, или имя слота указано не верно, функция возвращает значение false.
Рис. 5.16. Результат использования функции fact-slot-value
Выполните в среде CLIPS следующий пример:
Пример 5.20. Использование функции fact-slot-value
(clear)
(deftemplate foo
(slot bar)
(multislot yak)
(assert (foo (bar 1) (yak 23)))
(fact-slot-value 0 bar)
(fact-slot-value 0 yak)
(assert (another a b с))
(fact-slot-value 1 implied)
Если предыдущий пример был выполнен без ошибок, то полученный результат должен соответствовать приведенному на рис. 5.16.
5.2.10. Функции сохранения и загрузки списка фактов
Как можно заметить, наполнение списка фактов в CLIPS довольно кропотливое и длительное занятие. Если фактов достаточно много, этот процесс может растянуться на несколько часов, или даже дней. Так как список фактов хранится в оперативной памяти компьютера, теоретически, из-за сбоя компьютера или, например, неожиданного отключения питания, список фактов можно безвозвратно потерять. Чтобы этого не произошло, а так же для того чтобы сделать работу по наполнению базы знаний фактами более удобной, CLIPS предоставляет команды сохранения и загрузки списка фактов в файл — save-facts и load-facts соответственно.
Определение 5.14. Синтаксис команды save-facts
(save-facts <имя-файла> [<границы-видимости> <список-шаблонов >])
<границы-видимости> ::= visible|local
Команда save-facts сохраняет факты из текущего списка фактов в текстовый файл. На каждый факт отводится одна строчка. Неупорядоченные факты сохраняются вместе с именами слотов. В функции существует возможность ограничить область видимости сохраняемых фактов. Для этого используется аргумент <границы-видимости>. Он может принимать значение local или visible. В случае если этот аргумент принимает значение visible, то сохраняются все факты, присутствующие в данный момент в системе. Если в качестве аргумента используется ключевое слово local, то сохраняются только факты из текущего модуля. О модулях речь пойдет в гл. 12. По умолчанию аргумент <границы-видимости> принимает значение local. После аргумента <границы-видимости> может следовать список определенных в системе шаблонов. В этом случае будут сохранены только те факты, которые связаны с указанными шаблонами.
Пример 5.21. Использование функции save-facts
(clear)
(deftemplate template
(slot a)
(slot b))
(assert (template (a 1) (b 2)))
(assert (simple-factl) (simple-fact2))
(save-facts fl local template simple-factl)
Последовательность действий, приведенная в данном примере, сохраняет в файл f1, находящийся в текущем каталоге, все факты, видимые в текущем модуле и связанные с шаблонами template и simple-factl (как вы помните, после добавления факта simple-factl CLIPS определяет неявно созданный шаблон simple-factl). В результате будет получен текстовый файл со следующим содержанием:
Пример 5.22. Содержание файла fl
(template (а 1) (b 2) } (simple-factl)
В случае успешного выполнения, команда возвращает значение true, a в случае неудачи — соответствующее сообщение об ошибке. Если указанный файл уже существует, он будет перезаписан.
Для загрузки сохраненных ранее файлов используется функция load-facts. Функция имеет следующий формат:
Определение 5.15. Синтаксис команды load-facts
(load-facts <имя-файла>)
Здесь <имя-файла> — имя текстового файла, сохраненного ранее с помощью команды save-facts, содержащего список фактов. Файл со списком фактов можно также создать в любом текстовом редакторе, если вы хорошо разобрались с представлением фактов в CLIPS. Для загрузки сохраненного в предыдущем примере файла выполните:
Пример 5.23. Использование функции load-facts
(load-facts fl)
В случае успешного выполнения команда возвращает значение true, а в случае неудачи — false и соответствующее сообщение об ошибке. Обратите внимание, что если в файле содержатся факты, связанные с явно созданными с помощью конструктора deftemplate шаблонами, то в момент загрузки все необходимые шаблоны должны быть уже определены в системе. Если это условие не будет выполнено, то загрузка фактов закончится неудачно. К счастью, CLIPS также позволяет и загрузку конструкторов из текстового файла, но об этом мы поговорим в следующей главе, после рассмотрения конструктора defrule.
Кроме описанных выше функций и команд работы с шаблонами, фактами и предопределенными фактами, в CLIPS существует еще несколько полезных функций и команд, служащих той же цели. Полное описание этих функций и команд приведено в гл. 15 и 16. Далее, имея достаточный объем знаний о фактах в CLIPS и способах работы с ними, приступим к изучению правил.
ГЛАВА 6. Правила.
CLIPS поддерживает эвристическую и процедурную парадигму представления знаний. Для представления знаний в процедурной парадигме CLIPS предоставляет такие механизмы, как глобальные переменные, функции и родовые функции, речь о которых пойдет в гл. 7, 8 и 10 соответственно. В этой главе мы рассмотрим такой способ представления знаний, как правила. Правила в CLIPS служат для представления эвристик или так называемых "эмпирических правил", которые определяют набор действий, выполняемых при возникновении некоторой ситуации. Разработчик экспертной системы определяет набор правил, которые вместе работают над решением некоторой задачи. Правила состоят из предпосылок и бедствия. Предпосылки называются также ЕСЛИ-частъю правила, левой частью правила или LHS правила (left-hand side of rule). Следствие называется ТО-частью правила, правой частью правила или RHS правила (right-hand side of rule).
Предпосылки правила представляют собой набор условий (или условных элементов), которые должны удовлетвориться, для того чтобы правило выполнилось. Предпосылки правил удовлетворяются в зависимости от наличия или отсутствия некоторых заданных фактов в списке фактов (о котором было рассказано в предыдущей главе) или некоторых созданных объектов, являющихся экземплярами классов, определенных пользователем (о которых будет рассказано в гл. 11). Один из наиболее распространенных типов условных выражений в CLIPS — образцы (patterns). Образцы состоят из набора ограничений, которые используются для определения того, удовлетворяет ли некоторый факт или объект условному элементу. Другими словами, образец задает некоторую маску для фактов или объектов. Процесс сопоставления образцов фактам или объектам называется процессом сопоставления образцов (pattern-matching). CLIPS предоставляет механизм, называемый механизмом логического вывода (inference engine), который автоматически сопоставляет образцы с текущим списком фактов и определенными объектами в поисках правил, которые применимы в данный момент.
Следствие правила представляется набором некоторых действий, которые необходимо выполнить, в случае если правило применимо к текущей ситуации. Таким образом, действия, заданные вследствие правила, выполняются по команде механизма логического вывода, если все предпосылки правила удовлетворены. В случае если в данный момент применимо более одного правила, механизм логического вывода использует так называемую стратегию разрешения конфликтов (conflict resolution strategy), которая определяет, какое именно правило будет выполнено. После этого CLIPS выполняет действия, описанные вследствие выбранного правила (которые могут оказать влияние на список применимых правил), и приступает к выбору следующего правила. Этот процесс продолжается до тех пор, пока список применимых правил не опустеет.
Чтобы лучше понять сущность правил в CLIPS, их можно представить в виде оператора if-then, используемого в процедурных языках программирования, например, таких как Ada или С. Однако условия выражения if-then в процедурных языках вычисляются только тогда, когда поток управления программы непосредственно попадает на данное выражение путем последовательного перебора выражений и операторов, составляющих программу. В CLIPS, в отличие от этого, механизм логического вывода создает и постоянно модифицирует список правил, условия которых в данный момент удовлетворены. Эти правила запускаются на выполнение механизмом логического вывода. С этой стороны правила похожи на обработчики сообщений, присутствующие в таких языках программирования, как, например, Ada или Smalltalk.
Без правил не обойдется ни одна экспертная система, так что правила и язык их представления в экспертной системе можно смело назвать самой важной частью любой экспертной оболочки. Успех экспертной системы во многом определяется тем, насколько удачен способ представления знаний в виде правил, и насколько хорошо им владеет разработчик экспертной системы. Вся данная глава посвящена правилам, их синтаксису и способам построения, их функционированию и назначению, а также приемам их применения.
6.1. Создание правил. Конструктор defrule
Для добавления новых правил в базу знаний CLIPS предоставляет специальный конструктор defrule. В общем виде синтаксис данного конструктора можно представить следующим образом:
Определение 6.1. Синтаксис конструктора defrule
(defrule
<имя-правила>
[<комментарии>]
[<определение-свойства-правила>]
<предпосылки > ; левая часть правила
=>
<следствие> ; правая часть правила
)
Имя правила должно быть значением типа symbol. В качестве имени правила нельзя использовать зарезервированные слова CLIPS, которые были перечислены ранее. Повторное определение существующего правила приводит к удалению правила с тем же именем, даже если новое определение содержит ошибки.
Комментарии являются необязательными, и, как правило, описывают назначения правила. Комментарии необходимо заключать в кавычки. Эти комментарии сохраняются и в дальнейшем могут быть доступны при просматривании определения правила.
Определение правила может содержать объявление свойств правила, которое следует непосредственно после имени правила и комментариев. Более подробно свойства правила будут рассмотрены ниже.
В справочной системе и документации по CLIPS для обозначения предпосылок правила чаще всего используется термин "LHS of rule", а для обозначения следствия "RHS of rule", поэтому в дальнейшем мы будем использовать аналогичную терминологию — левая и правая часть правила.
Левая часть правила задается набором условных элементов, который обычно состоит из условий, примененных к некоторым образцам. Заданный набор образцов используется системой для сопоставления с имеющимися фактами и объектами. Все условия в левой части правила объединяются с помощью неявного логического оператора and. Правая часть правила содержит список действий, выполняемых при активизации правила механизмом логического вывода. Для разделения правой и левой части правил используется символ =>. Правило не имеет ограничений на количество условных элементов или действий. Единственным ограничением является свободная память вашего компьютера. Действия правила выполняются последовательно, но тогда и только тогда, когда все условные элементы в левой части этого правила удовлетворены.
Если в левой части правила не указан ни один условный элемент, CLIPS автоматически подставляет условие-образец initial-fact или initial-object. Таким образом, правило активизируется всякий раз при появлении в
базе знаний факта initial-fact ИЛИ Объекта initial-object. О факте initial-fact было рассказано в предыдущей главе, об объекте initial-object вы узнаете в гл. 11. Если в правой части правила не определено ни одно действие, правило может быть активировано и выполнено, но при этом ничего не произойдет.
Более подробно синтаксис левой и правой части правил будет описан далее в этой главе, а пока, в качестве демонстрации применения правил, напишем простейшую CLIPS-программу, которая по традиции здоровается со всем миром, сразу после своего рождения. Вы наверно знакомы с текстом подобных программ для процедурных языков программирования, таких как, например, С. На языке CLIPS такая программа будет выглядеть следующим образом:
Пример 6.1. Программа "Hello-World!"
(clear)
(defrule
Hello-World
"My FirstCLIPS Rule"
=>
(printout t crlf crlf)
(printout t ******************** crlf)
(printout t "* HELLO WORLD!!! *" crlf)
(printout t ******************** crlf)
(printout t crlf crlf)
(reset)
(run)
Так как это первая наша программа на языке CLIPS, разберем подробно все ее действия и то, каким образом они выполняются.
Функция clear полностью очищает систему, т. е. удаляет все правила, факты и прочие объекты базы знаний CLIPS, добавленные конструкторами, приводит систему в начальное состояние, необходимое для каждой новой программы.
Затем, с помощью конструктора defrule в систему добавляется новое правило с именем Hello-World и соответствующими комментариями. Левая часть правила в данном случае отсутствует, поэтому CLIPS автоматически формирует предпосылки, состоящие из единственного условного выражения (initial-fact). Это выражение является образцом простейшего типа. При запуске программы на выполнение механизм логического вывода CLIPS будет искать в списке фактов факт (initial-fact) и если он там будет найден — активизирует правило. Правая часть нашего правила состоит из нескольких вызовов функции printout. Подробно данная функция будет рассмотрена в гл. 15. Сейчас же вам необходимо знать только то, что эта функция выводит текстовое выражение в один из потоков вывода. Параметр t задает стандартный поток вывода — экран. Он аналогичен, например, стандартному потоку cout в C++. Выражение clrf служит для перехода на новую строку.
Функция reset, как уже упоминалось ранее, очищает список фактов и заносит в него факт (initial-fact), что очень важно для нормального функционирования нашей программы. И, наконец, функция run запускает механизм логического вывода и приводит нашу программу в движение. Если описанные выше действия были выполнены правильно, то вы должны увидеть результат, аналогичный приведенному на рис. 6.1 — фразу "hello world!!!" в красивой рамочке из звездочек:
Рис. 6.1. Результат работы программы "Hello-World!"
Чтобы запустить нашу программу на выполнение еще раз, достаточно вызвать функции reset и run. Эти функции можно вводить с клавиатуры, кроме того, они доступны в меню Execution и имеют "горячие" клавиши <Ctrl>+<E> и <Ctrl>+<R> соответственно.
CLIPS поддерживает ряд функций, команд и визуальных средств, необходимых для эффективной работы с правилами. Самые основные из них будут рассмотрены в данной главе по мере необходимости. Полный список функций и команд, предназначенный для работы с правилами, будет приведен в гл. 15 и 16 соответственно. Сейчас же рассмотрим визуальный инструмент, доступный пользователям Windows-версии среды CLIPS — Defrule Manager (Менеджер правил). Для запуска менеджера правил в меню Browse выберите пункт Defrule Manager. Внешний вид этого инструмента показан на рис. 6.2.
Рис. 6.2. Окно менеджера правил
Менеджер отображает список правил, присутствующих в системе в данный момент, и позволяет выполнять над ними ряд операций. Например, с помощью кнопки Remove можно удалить выбранное правило из системы, а с помощью Pprint вывести в окне CLIPS определение выделенного правила вместе с введенными комментариями. Общее количество правил отображается в заголовке окна менеджера — Defrule Manager — 1 Items. Другие возможности менеджера правил будут рассмотрены позже, по мере необходимости.
Как вы уже могли убедиться, разбирая приведенный выше пример несложной программы, довольно тяжело создать даже минимально полезную программу на языке CLIPS, не представляя себе, что именно происходит при выполнении вашей программы. При создании экспертных систем необходимо точно знать, как происходит сопоставление образцов, заданных в левой части правила, каким именно образом выбирается правило для выполнения и т. д. Именно поэтому в последующих разделах мы остановимся на внутренних алгоритмах представления и обработки правил в CLIPS, а уже затем перейдем к описанию функций и команд, связанных с правилами.
6.2. Основной цикл выполнения правил
После того как в систему добавлены все необходимые правила и приготовлены начальные списки фактов и объектов, CLIPS готов выполнять правила. В традиционных языках программирования точка входа, точка остановки и последовательность вычислений явно определяются программистом. В CLIPS поток исполнения программы совершенно не требует явного определения. Знания (правила) и данные (факты и объекты) разделены, и механизм логического вывода, предоставляемый CLIPS, применяет данные к знаниям, формируя список применимых правил, после чего последовательно выполняет их. Этот процесс называется основным циклом выполнения правил (basic cycle of rule execution). Рассмотрим последовательность действий (шагов), выполняемых системой CLIPS в этом цикле в момент выполнения нашей программы:
- Если был достигнут предел выполнения правил или не был установлен текущий фокус, выполнение прерывается. В противном случае, для выполнения выбирается первое правила модуля, на котором был установлен фокус. Если в текущем плане выполнения нет удовлетворенных правил, то фокус перемещается по стеку фокусов и устанавливается на следующий модуль в списке. Если стек фокусов пуст, выполнение прекращается. Иначе шаг 1 выполняется еще один раз. Более подробно о модулях и фокусе будет рассказано в гл. 12.
- Выполняются действия, описанные в правой части выбранного правила. Использование функции return может менять положение фокуса в стеке фокусов. Число запусков данного правила увеличивается на единицу, для определения предела выполнения правила.
- В результате выполнения шага 2 некоторые правила могут быть активированы или дезактивированы. Активированные правила (т. е. правила, условия которых удовлетворяются в данный момент) помещаются в план решения задачи модуля, в котором они определены. Размещение в плане определяется приоритетом правила (salience) и текущей стратегией раз решения конфликтов (эти понятия будут описаны ниже). Дезактивированные правила удаляются из текущего плана решения задачи. Если для правила установлен режим просмотра активаций, то пользователь получит соответствующее информационное сообщение при каждой активации или дезактивации правила (режим просмотра активаций можно установить с помощью диалогового окна Watch Options. Для этого выберите пункт Watch в меню Execution и установите флажок Activations).
- Если установлен режим динамического приоритета (dynamic salience), то для всех правил из текущего плана решения задачи вычисляются новые значения приоритета. После этого цикл повторяется с шага 1.
6.3. Свойства правил
Для более полного понимания материала, изложенного далее в этой главе, необходимо разобраться с таким понятием, как свойства правил. Свойства правил позволяют задавать характеристики правил до описания левой части правила, как было в разд. 6.1. Для задания свойства правила используется ключевое слово declare. Одно правило может иметь только одно определение свойства, заданное с помощью declare.
Определение 6.2. Синтаксис свойств правил
<определение-свойства-правила> ::= (declare <свойство-правила>)
<свойство-правила> ::= (salience <целочисленное выражение>)
(auto-focus TRUE FALSE)
6.3.1. Свойство salience
Свойство правила salience позволяет пользователю назначать приоритет для своих правил. Объявляемый приоритет должен быть выражением, имеющим целочисленное значение из диапазона от —10 000 до +10 000. Выражение, представляющее приоритет правила, может использовать глобальные переменные и функции (которые будут описаны в гл. 7 и 8 соответственно). Однако старайтесь не указывать в этом выражении функций, имеющих побочное действие. В случае если приоритет правила явно не задан, ему присваивается значение по умолчанию — 0.