- •Оглавление
- •Предисловие
- •1. Общие сведения о языке и среде разработки CLIPS
- •1.1. Системы продукций и CLIPS
- •1.2. Основы работы в консоли CLIPSJNI
- •1.3. Основы работы в среде CLIPSWin
- •1.4. Механизмы представления знаний в CLIPS
- •1.5. Пример разработки БЗ и работы с ней в среде CLIPS
- •1.6. Пример использования эвристического механизма представления знаний совместно с процедурным
- •2. Основные конструкции языка CLIPS
- •2.1. Примитивные типы данных языка CLIPS
- •2.2. Особенности вызова функций в языке CLIPS
- •2.3. Факты в языке CLIPS
- •2.3.1. Позиционные факты
- •2.3.2. Непозиционные факты
- •2.4. Операции над фактами
- •2.5. Правила в языке CLIPS
- •2.5.1. Объявление и добавление новых правил
- •2.5.2. Один из подходов к разрешению конфликтов
- •2.6. Групповые символы для простых и составных полей
- •2.7. Переменные в CLIPS
- •2.8. Глобальные переменные
- •2.9. Пользовательские функции
- •3. Примеры построения простых интеллектуальных систем
- •3.1. Разработка простейшей экспертной системы
- •3.2. Пример решения задач на планирование
- •3.2.1. Программа ”Робот и ящик”
- •3.2.2. Запуск и трассировка программы ”Робот и ящик”
- •3.3. Пример использования ООП в CLIPS.
- •Приложение 2. Использование образцов в правилах.
- •Приложение 3. Стратегии разрешения конфликтов
- •Приложение 4. Работа с модулями в CLIPS
- •Литература и Интернет-ресурсы
находится в том помещении (location RoomA), куда он должен был доставить груз (to RoomA). Таким образом, миссия окончена и программа останавливается. Результат этого шага – робот свою работу выполнил и отключился.
Упражнение 3.2 .
1.Кроме рассмотренного, провести трассировку и для других случаев:
•робот и ящик в разных помещениях, но груз остается на месте,
•робот и ящик в одном помещение, но груз остается там же,
•робот и ящик в одном помещение, но груз надо переместить. Выполняя трассировку, составить таблицу последовательности применения правил для каждого из этих случаев.
2.Доработать программу таким образом, чтобы обо всех изменениях в состоянии системы робот-ящик выдавались текстовые сообщения в консоли CLIPS. Проверить результаты для всех четырех случаев, а затем отключить трассировку.
3.Изменяя исходные данные системы, вы наверно обратили внимание насколько неудобно делать их внутри программы. Предлагается это делать с помощью разработанного вами внешнего интерфейса по заданию местоположений робота и ящика, а также направлению перемещения.
4.Не кажется ли вам странным, что железный робот после каждой операции останавливается и для каждого следующего действия необходимо заново пускать программу и задавать его местоположение. Изменить программу таким образом, чтобы обеспечивалось ее циклическое выполнение до какого-либо дополнительного условия.
5.Но если наша простая система оперирует всего двумя маршрутами ”машина-склад” или “склад-торговый_зал”, а программа работает в цикле и постоянно знает местонахождение робота, то может не надо указывать каждый раз, где кто находиться и куда чего вести. Доработать интерфейс, что бы можно было выбирать из возможных действий: ”груз с машины на склад” или ”груз со склада на машину”. Замечание. Причем однотипные действия могут повторяться.
6.Вариантов из реального мира для этой простой задачки может быть бесконечное множество. Реализация любых из них приветствуется, но при условии выполнения первых пяти из них, которые должны быть сохранены в отдельных файлах robot_n.clp.
3.3. Пример использования ООП в CLIPS.
Рассмотрим следующую задачу. Необходимо разработать и реализовать объектную модель автомата по продаже газированной воды. Вода может быть выдана как с сиропом (стоимостью 3 копейки), так и без сиропа (стоимостью 1 копейка). Количество сиропа и воды ограничено.
55
Автомат по продаже воды реализован в виде класса water-automate, родительским классом которого является USER, класс не абстрактный (role concrete). Чтобы класс мог быть использован при сопоставлении образцов во время выполнения правил pattern-match выставлен как reactive. У класса имеются два слота gas-water и syrup, доступные как для чтения, так и для записи (create-accessor read-write). Данные слоты будут использоваться для хранения количества порций воды и сиропа, их тип задается как INTEGER.
Объект класса water-automate, который создается в программе, будет называться our-automate. В качестве значений по умолчанию для каждого слотов задаются значения 2 и 3, соответственно. Эти значения определяют максимально возможное в нашем автомате количество порций воды (2) и сиропа (3).
Выдачу воды реализуем в обработчике сообщений getwater, в который в качестве параметра будем передавать номинал монеты. Вызов данного сообщения реализуем в правиле, которое будет выполняться, когда в базе фактов появится факт со словом money и номиналом монеты.
Правило give-money реализует интерфейс по работе с программой, выполняя функцию монетоприемника автомата с газированной водой. Ниже приводится с большим числом комментариев пример реализации данной задачи с использованием ООП CLIPS. Данный пример представляет собой частично доработанную программу, представленную на сайте http://fkn.ktu10.com/?q=node/2182.
; |
-------------------------------------------- |
|
! |
;----- |
Program "Gas water automate ” |
-----! |
|
;----- |
This |
is file avtomat.clp |
-----! |
;-------------------------------------------- |
|
|
! |
;--- |
определение |
класса |
|
(defclass gas-water-automate |
|
(is-a USER) |
;родительский класс |
(role concrete) |
;класс неабстрактный |
(pattern-match reactive) |
;класс активный |
(slot gas-water (type INTEGER) |
;вода |
(create-accessor read-write)) |
|
(slot syrup (type INTEGER) |
;cиpon |
(create-accessor read-write)) |
|
) |
|
;---объявляем экземпляр класса |
|
(definstances automates |
|
(our-automate of gas-water-automate |
|
(gas-water 2) |
|
(syrup 3) |
|
) |
|
) |
|
56
;---обработчик сообщений
(defmessage-handler gas-water-automate getwater (?money) (if (= ?money 1) then
;--если 1коп, то выдаем воду без сиропа ;--если воды нет - оповещаем об этом
(if (> (dynamic-get gas-water) 0) then (dynamic-put gas-water
(- (dynamic-get gas-water) 1)) (printout t "Your gas-water, please" crlf)
else
(printout t "Sorry, no more gas-water" crlf)
)
else
(if (= ?money 3) then
;;--если 3 коп, то выдаем воду с сиропом ;;--если воды или сиропа0 нет, то оповещаем об этом
(if (and (> (dynamic-get gas-water) 0) (> (dynamic-get syrup) 0)) then
(dynamic-put gas-water
(- (dynamic-get gas-water) 1)) (dynamic-put syrup (- (dynamic-get syrup) 1))
(printout t "Your gas-water with syrup, please"
crlf)
else
(printout t "Sorry, no more gas-water or syrup"
crlf)
)
else
;--ecли не 1 и не 3 коп, то сообщаем об этой ошибке
(printout t "Wrong money" crlf)
)
)
)
;---правило выполняется когда в базе фактов есть монеты
(defrule drinkwater
?ind <- (money ?money) =>
;--вызов обработчика сообщений
(send [our-automate] getwater ?money) ;--удаляем факт
(retract ?ind)
)
57
(defrule give-money (not (money ?)) =>
(printout t "Input you money -> " ) (bind ?answer (read))
(if (eq ?answer 0) then (halt)
else (assert(money ?answer))
))
Упражнение 3.3.
•Познакомится с теоретическими основами ООП в CLIPS. Разобраться в структуре программы и назначением отдельных ее фрагментов.
•Провести тестирование и трассировку программы. Если все было сделано верно, то экран консоли CLIPS будет как на рис. 3.6.
•Доработайте программу так, чтобы можно было проводить настройку максимального количества порций автомата из программы, а еще лучше из конфигурационного файла.
Рис. 3.6. Результат выполнения программы.
Краткие сведения об объектно-ориентированных средствах CLIPS
Использование объектно-ориентированных средств в CLIPS позволяет значительно упростить программирование правил, поскольку для обновления данных можно применять механизм передачи и обработки сообщений методами классов. Конструктор определения класса имеет вид:
(defclass <имя-класса> [<комментарии>] (is-a <список-суперклассов>+) [ <роль-класса> ] [ <активность-класса> ]
<слот>* <объявление-обработчика-сообщений>*
)
58
Каждый создаваемый пользователем класс должен быть напрямую унаследован хотя бы от одного класса (обычно от OBJECT). Если класс Б наследуется от А, то Б является потомком А, а А - родителем Б. Например,
(defclass A (is-a USER))
В этом случае класс А является прямым наследником класса USER и список старшинства классов для него будет – A: A USER OBJECT. Новый класс наследует слоты и сообщения от своих родителей.
(defclass A (is-a USER) (slot fooA)
(slot barA))
(defclass В (is-a A) (slot fooB)
(slot barB))
Список старшинства для класса A: A USER OBJECT, а его экземпляр будет иметь 2 слота – fooA и barA. В то же время, список старшинства для класса В: В A USER OBJECT, а его экземпляр будет иметь уже 4 слота: fooB, barB, fooA, barA.
Для создания экземпляра любого определенного ранее класса в CLIPS используется команда (make-instance … of …). Так, например команда (make-instance a of А) создает экземпляр класса А с именем а. Другим вариантом создание массива экземпляра классов является использование конструктора definstances:
(definstances my_inst (a of A)
(b of A)
(c of A))
Но для того, чтобы можно было создавать экземпляры какого-либо класса, иметь доступ к его слотам и выполнять какие-либо действия, прежде всего, необходимо, чтобы этот класс существовал. При создании любого нового класса необходимо описать все свойства вновь создаваемого класса и его обработчик сообщений.
Описатели классов
К числу основных описателей класса обычно относят <роль-класса>, <активность-класса>, <слот> и <объявление-обработчика-сообщений>. Что касается первых двух описателей классов, то следует отметить, что они являются необязательными при объявление классов и имеют следующие семантические конструкции:
<роль-класса> |
::= |
(role concrete | abstract) |
<активность-класса> |
::= |
(pattern-match reactive | non-reactive) |
59
Первая из них указывает на абстрактность или конкретность класса, который объявляется. Абстрактный класс (role abstract) предназначен только для наследования. На его основе не могут создаваться экземпляры. На основе конкретного класса (role concrete) могут создаваться его экземпляры.
Что касается обработчиков сообщений, то следует отметить, что любые изменение значений свойств объектов по правилам ООП производится самими объектами, поэтому при описании класса дается только объявление обработчика сообщений, а сам он описывается отдельно.
Одним из основных описателей классов, особенно для простейших задач, является слот, синтаксическая конструкция которого имеет вид:
<слот> ::= (slot <имя> <тип>…<знач-по-умолчанию>)| (single-slot <имя> <тип>…<знач-по-умолчанию>)| (multislot <имя> <тип>…<знач-по-умолчанию>
Слот – это место хранения значений поля класса. Каждый экземпляр класса содержит копию всех слотов своего родителя. Количество слотов класса ограничено только размером свободной памяти. Имя слота - любой набор символов, за исключением зарезервированных слов.
Слот может содержать одно или несколько значений. По умолчанию он содержит только одно значение. Ключевое слово multislot устанавливает тип слота, позволяющий хранить несколько значений, a slot или singleslot устанавливает тип слота, который может содержать только одно значение.
Многозначные слоты хранятся как значения с несколькими полями и для манипуляций с ними используют стандартные функций nth$ и lengths. Для установки значения слота используется функция slotinsertS.
CLIPS> (clear) CLIPS>
(defclass myClass (is-a USER) (role concrete)
(multislot my_slot (create-accessor read)
(default myText1 newText mySymbol)
)
)
CLIPS> (make-instance myObj of myClass) [myObj] [myObj]
CLIPS> (nth$ 2 (send [myObj] get-my_slot)) newText
CLIPS>
Если при создании слота указывается модификатор для создания методов для записи или чтения по умолчанию (create-accessor read-write), то экземпляр класса будет реагировать на сообщения get-имя_слота или putимя_слота соответственно чтением и записью значения слота. Создание обработчиков сообщений будет рассмотрено позже.
60
Для каждого слота может быть определен набор фасетов. Фасеты описывают различные свойства слотов: значения по умолчанию, вид хранения, видимость и т.п. Коротко рассмотрим некоторые из них:
• Фасеты для задания значений по умолчанию. Эти фасеты используют для определения значений слота по умолчанию при создании экземпляра класса. Фасет default используется для задания статических значений слота. Фасет default-dynamic используется для заданий значения слота, которое задается всякий раз при создании нового экземпляра класса.
CLIPS> (clear) (setgen 1)
(defclass A (is-a USER) (role concrete)
(slot foo (default-dynamic (gensym)) (create-accessor read)
)
)
(make-instance al of A) (make-instance a2 of A) CLIPS> (send [al] get-foo) genl
CL1PS> (send [a2] get-foo) gen2
• Фасет Storage. Он определяет, будет ли значение слота храниться локально в экземпляре класса (local), либо это значение будет одно для всех экземпляров класса (shared). Рассмотрим пример:
(clear)
(defclass myClass (is-a USER) ;объявляем класс myClass (role concrete)
(slot mySlotShare (create-accessor write) (storage shared)
(default 1))
(slot mySlotLocal (create-accessor write) (storage local))
) |
|
(make-instance myObj of myClass) |
;создаем объект myObj |
(send [myObj] print) |
|
(send [myObj] put-mySlotShare 111) |
;переопределяем слот |
(send [myObj] put-mySlotLocal 222) |
;переопределяем слот |
(send [myObj] print) |
|
(make-instance newObj of myClass) |
;создаем объект newObj |
(send [newObj] print) |
|
Приведенный набор команд можно сохранить в командном файле, который потом можно загрузить с помощью File –> Load Batch, или ввести этот набор команд в редакторе CLIPS, выделить их и затем выполнить Batch Selection. В любом из этих вариантов CLIPS выполнить набор действий, которые частично откомментированы в приведенном выше
61
тексте и позволит вам определить различие в значениях local и shared фасета storage. Это же различие иллюстрирует и результат выполнения последней команды этого примера:
CLIPS> (send [newObj] print) [newObj] of myClass (mySlotShare 111) (mySlotLocal nil)
CLIPS>
• Фасет типа доступа к слоту. Для слота может быть задано три типа фасетов: read-write, read-only и initialize-only. Подробно останавливаться на их описание не будем, так как для простейших задач их назначение следует из их названия.
Обработчики сообщений
Изменение значений свойств объектов по правилам ООП производится самими объектами, поэтому в языке CLIPS это реализовано посредством обработчиков сообщений. Синтаксис команды для создания обработчика сообщений имеет обобщенный вид:
(defmessage-handler <class-name> <message-name> [<handler-type>] [<comment>] (<parametr>* [<wildcard-parameter>]) <action> *
)
Для вызова обработчика сообщений экземпляра класса используется команда вида:
(send [имя экземпляра] имя_метода параметры)
Обработчик сообщений уникально идентифицируется наименованием, наименованием класса и типом. Для класса обработчик сообщений может задаваться как при создании определения класса, так и после. Заметим, что при создании определения класса создается только заголовок обработчика сообщений. Собственно программный код обработчика создается позже при помощи команды defmessage-handler. Рассмотрим пример:
;-- создаем класс «прямоугольник» и объявляем у него ;-- обработчик сообщений, позволяющий находить его площадь
(defclass rectangle (is-a USER) (slot side-a (default 1)) (slot side-b (default 1)) (message-handler find-area)
)
;-- создаем тело обработчика сообщений
(defmessage-handler rectangle find-area () (* ?self:side-a ?self:side-b)
)
62
;-- создаем ещё один обработчик сообщений, позволяющий ;-- напечатать полученную площадь прямоугольника
(defmessage-handler rectangle print-area () (printout t (send ?self fmd-area) crlf)
)
Ссылка на активный, то есть принимающий сообщение в данный момент экземпляр сущности может быть получена при помощи переменной ?self, имя которой зарезервировано в системе. Рассмотрим еще один пример командного файла:
(clear)
(defclass myClass (is-a USER) (role concrete)
(slot mySlot_1 (default 1)) (slot mySlot_2 (default 2))
)
(defmessage-handler myClass print-all-slots () (printout t "It is the test for handler" crlf) (printout t ?self:mySlot_1 " " ?self:mySlot_2 crlf)
)
(make-instance myObj of myClass) (send [myObj] print-all-slots)
Результат выполнения последней команды этого файла подтверждает работоспособность созданного нами обработчика сообщений:
CLIPS> (send [myObj] print-all-slots) It is the test for handler
1 2
Рис. 3.7. Результат выполнения программы.
Если теперь открыть Browse –> Defclass Manager, то можно убедиться в том, что объявленный нами класс существует в системе. И этот класс, наряду с предопределенными обработчиками get и put, имеет и сформированный нами обработчик put-all-slots (рис.3.7).
63
3.4. Вызов CLIPS программ из командной строки и из
VBScript.
До текущего момента в основном рассматривались вопросы разработки и создания программ на CLIPS. При этом вся работа выполнялась внутри Windows-среда CLIPS. Однако CLIPS обладает способностью быть встроенным в различные приложения. Знакомство по интеграции CLIPS с С, С++ и Java можно найти в технической документации на систему. А в этом разделе будут рассмотрены несколько демонстрационных примеров по загрузке и запуску CLIPS-приложений из разных сред.
Прежде всего, хотелось бы отметить, что наряду с оконной реализацией CLIP, существуют и консольные реализации. В том числе под Ubuntu, Linux и другие ОС. Что касается Windows, то для нее тоже есть консольная версия clipscmd.exe, которая запускается в командной строки (рис. 3.8) и может быть использована в командных сценариях.
Рис. 3.8. Результат запуска CLIPS в командной строке.
Кроме того, CLIPS при запуске позволяет выполнять командные файлы собственного формата. Для реализации этой возможности CLIPS следует запустить с одним из трех возможных аргументов:
clipscmd –f <имя-файла> clipscmd –f2 <имя-файла> clipscmd –l <имя-файла>
Текстовый файл, заданный с помощью опции –f, должен содержать команды CLIPS. Если он содержит команду exit, то CLIPS завершит свою работу и пользователь вернется в операционную систему. В случае если команда exit отсутствует, то после выполнения всех команд этого файла пользователь попадет в консоль самого CLIPS. Все конструкции языка CLIPS, включаемые в командный файл, должны быть набраны так же, как если бы они вводились непосредственно в командную строку CLIPS.
Опция –f фактически эквивалентна запуску команды batch сразу после запуска CLIPS. Опция –f2 практически аналогична опции –f, но за одним
64
отличием. Она подавляет вывод трассировочный информации при загрузку командного файла, и аналогична команде batch*. Опция –l определяет текстовый файл, содержащий конструкторы CLIPS, которые тут же запускаются на выполнение. Использование этой опции эквивалентно использованию команды load сразу после запуска CLIPS.
В дальнейшем изложение будем ссылаться на пример, который был рассмотрен в разделе 3.1 и представлял собой небольшую экспертную систему по диагностики двигателя автомобиля. Для ее запуска был создан файл es_start.bat, который представлял собою командный файл CLIPS. Его загружали из оконной среды CLIPS, используя File -> Load Batch … . Аналогичную операцию можно выполнить и в командной строке Windows, но используя теперь консольную версиею CLIPS, задавая при ее вызове имя этого же командного файла с опцией –f или –f2 (рис. 3.9).
Рис. 3.9. Запуск консольной версии CLIPS вместе с командным файлом.
Как видно из этого рисунка, введя консольную команду запуска CLIPS с параметрами, мы сразу входим в среду экспертной системы для получения консультацию по диагностики автомобиля. На людей, которые постоянно работают в оконной среде Windows, это не произведет впечатления. Но если вы подключаетесь к этой ЭС в удаленном терминальном доступе по SSH туннелю с использованием, например, PuTTy, то у вас может быть и другое мнение. Такого интерфейса может быть вполне достаточно. Но если современная графическая среда вам импонирует более, то и здесь есть простейший вариант использования консольной версии.
Замечание.
Хочу сразу предупредить, что рассматриваемый ниже материал носит чисто иллюстративный учебный характер, не претендую на готовую технологию разработки программных продуктов.
Рассмотрим еще один вариант использования консольной версии CLIPS при разработке и построения сценариев на базе VBScript или JavaScript. Особенность этого подхода заключается в том, что:
•запуск clipscmd.exe будет выполняться непосредственно из скрипта,
•скрипт принимает весь выходной поток CLIPS программы,
•из общего потока выделяет вопросы экспертной системы,
65
•транслирует эти вопросы пользователю, но уже в графической среде создаваемой самим скриптом,
•ожидает реакции пользователя на эти вопросы и возвращает их во входной поток CLIPS программы,
•по окончанию консультации выводит результаты заключения,
•обеспечивает удаление из OC созданного этим скриптом процесса в
конце консультации и в случаях ее прерывания пользователем. Особенности скриптов состоят в том, что они выполняются средствами
операционной системы. Сервер сценариев Windows (Windows Script Host), под управлением которого выполняются сценарии, обладает способностью работать в "невидимом" режиме, когда при запуске скриптов никаких вопросов или дополнительных системных сообщений выводиться не будет.
При использовании метода Exec(<Command>) объекта WSH будет создан новый дочерний процесс, который запускает заданное консольное приложение. Возвращаемый объект WshExec позволяет контролировать ход выполнения приложения и обеспечивает доступ к потокам StdIn, StdOut и StdErr этого приложения.
Один из возможных примеров по доступу из VBScript к экспертной системе на CLIPS может иметь вид:
'!---------------------------------------------------- |
|
! |
'!------- |
Доступ из VBScript к ЭС на CLIPS ------- |
! |
'!---------------------------------------------------- |
|
! |
Set WshShell = WScript.CreateObject("WScript.Shell") |
|
|
Set oExec |
= WshShell.Exec("cmd") |
|
'запуск clips
cmdClips="D:/CLIPS/clipscmd.exe -f2 es_start.bat" oExec.StdIn.WriteLine cmdClips
txt = |
"Мини экспертная система" & vbCrLf |
txt = |
txt & "по диагностике автомобиля" + vbCrLf |
msgbox |
txt,48,"Подключение к CLIPS" |
'ожидание первого вопроса
Do
vopros = oExec.StdOut.Readline Loop While (InStr(vopros,"->") = 0)
DO
'прием ввода ответа с проверкой на отмену otvet = inputbox(vopros,"Введите ответ") if otvet="" then exit do
'отправка ответа в clips oExec.StdIn.WriteLine otvet
66
'прием из clips реакции на ответ vopros = oExec.StdOut.Readline
if InStr(vopros,"->") > 0 then
'принят новый вопрос
msgbox "Следующий вопрос ",64,"Внимание" elseif InStr(vopros,"Reenter") > 0 then
'принята реакция на ошибку в ответе msgbox vopros,,"Ошибка ВВОДА" vopros = oExec.StdOut.Readline
else
msgbox vopros,64,"Результат консультации" exit do
end if
LOOP
WshShell.Run "taskkill /IM cmd.exe", 0
WScript.Quit
В приведенной реализации скрипта имеет место построчный прием и анализ входного потока. Для анализа того, что в текущем потоке принят именно вопрос экспертной системы выбран набор символов "->". Надо проверить, что в CLIPS программе вывод вопроса заканчивается переводом строки. Если это не так, то необходимо внести изменения в программу:
(deffunction ask (?question)
(printout t "ES: " ?question " -> " crlf ) (bind ?answer (read))
?answer
)
Рис. 3.10. Результат запуска скрипта по доступу к программе на CLIPS.
После запуска скрипта на экран будет выдано сообщение о том, что командный процессор загружен, в него послана команда на запуск CLIP с подгрузкой командного файла и система готова к работе (рис. 3.10).
67
Нажав кнопку ОК, скрипт перейдет в режим консультации, когда CLIPS будет формировать последовательность задаваемых вопросов и выполнять согласование правил, используя свой встроенный механизм вывода. На скрипт возлагается только организация внешнего интерфейса (рис. 3.11).
Рис. 3.11. Результат запуска скрипта по доступу к программе на CLIPS.
При ошибках ввода пользователем ответа на вопрос скрипт совместно с CLIPS осуществляет соответствующую реакцию (рис. 3.12).
Рис. 3.12. Результат запуска CLIPS в командной строке.
Упражнение 3.3.
•Разобраться в примере программы и оттестировать ее работу.
•Используя за базу этот скрипт, организовать html доступ к ЭС.
•Заменить в CLIPS программе вывод сообщений на вывод некоторых кодов, а в скрипте сделать вывод русифицированных сообщений, соответствующих этим кодам.
68
ПРИЛОЖЕНИЕ
69
Приложение 1. Основные конструкторы и функции языка
CLIPS
Типы данных:
CLIPS поддерживает следующие типы данных: integer, float, string, symbol, external-address, fact-address, instance-name, instance-address.
Конструкторы для создания баз знаний (БЗ):
defrule – определение правил; deffacts – определение фактов; deftemplate – определение шаблона факта;
defglobal – определение глобальных переменных; deffunction – определение функций;
defmodule – определение модулей (совокупности правил); defclass – – определение классов;
defintances – определение объектов по шаблону, заданному defclass ; defmessagehandler – определение сообщений для объектов;
defgeneric – создание заголовка родовой функции; defmethod – определение метода родовой функции.
Процедурные функции:
if |
– оператор ветвления; |
while |
– цикл с предусловием; |
loop-for-count – итеративный цикл; |
|
prong |
– объединение действий в одной логической команде; |
prong$ |
– выполнение набора действий над каждым |
|
элементом поля; |
return |
– прерывание функции, цикла, правила и т.д.; |
break |
– то же, что и return, но без возвращения параметров; |
switch |
– оператор множественного ветвления; |
bind |
– создание и связывание переменных. |
Функций работы с базой фактов: |
|
assert |
– добавляет новые факты в список правил, |
retract |
– удаляет факты из списка фактов, |
modify |
– меняет в определенном факте значение слота, |
Функций работы со строками: |
|
str-cat |
– объединение строк, |
sym-cat |
– объединение строк в значение типа symbol, |
70
sub-string |
– выделение подстроки, |
str-index |
– поиск подстроки, |
eval |
– выполнение строки в качестве команды CLIPS, |
build |
– выполнение строки в качестве конструктора CLIPS, |
upcase |
– преобразование символов в символы верхнего регистра, |
lowcase |
– преобразование символов в символы нижнего регистра, |
str-compare |
– сравнение строк, |
str-length |
– определение длины строки, |
check-syntax |
– проверка синтаксиса строки, |
string-to-field |
– возвращение первого поля строки. |
Функции работы с составными величинами: |
|
create$ |
– создание составной величины, |
nth$ |
– получение элемента составной величины, |
members |
– поиск элемента составной величины, |
subset$ |
– проверка одной величины на подмножество другой, |
delete$ |
– удаление элемента составной величины, |
explode$ |
– создание составной величины из строки, |
implode$ |
– создание строки из составной величины, |
subseq$ |
– извлечение подпоследовательности |
|
из составной величины, |
replace$ |
– замена элемента составной величины, |
insert$ |
– добавление новых элементов в составную величину, |
first$ |
– получение первого элемента составной величины, |
rest$ |
– получение остатка составной величины, |
length$ |
– определение числа элементов составной величины, |
delete-member$ |
удаление элементов составной величины, |
|
replace-member$ замена элементов составной величины. |
||
Функции ввода-вывода |
||
open |
– открытие файла (виды доступа r, w, r+, a, wb ), |
|
close |
– закрытие файла, |
|
printout |
– вывод информации на заданное устройство, |
|
read |
– ввод данных с заданного устройства, |
|
readline |
– ввод строки с заданного устройства, |
|
format |
– форматированный вывод на заданное устройство, |
|
rename |
– переименование файла, |
|
remove |
– удаление файла. |
|
Эти функции используют следующие логические имена устройств:
stdin |
– устройство ввода, |
stdout |
– устройство вывода, |
wclips |
– устройство, используемое как справочное, |
71
wdialog |
– устройство для отправки пользователю сообщений, |
wdisplay |
– устройство для отображения правил, фактов и т.,п., |
werror |
– устройство вывода сообщений об ошибках, |
wwarning |
– устройство для вывода предупреждений, |
wtrase |
– устройство для вывода отладочной информации, |
Функции возвращающие значения true или false
Среди функций, которые возвращают значения true или false следует выделить следующие группы:
•функции булевой логики: and, or, not;
•функции сравнения чисел: =, ≠, >, ≥, <, ≤;
•предикативные функции для проверки принадлежности проверяемому типу: integerp, floatp, stringp, symbolp, pointerp (относится ли аргумент к xternal-address), numberp (относится ли аргумент к integer или float), lexemerp (относится ли аргумент к string или symbol), evenp (проверка целого на четность), oddp (проверка целого на нечетность), multifildp (является ли аргумент составным полем);
•функции сравнения по типу и по значению: eq, neq.
Математические функции
•Стандартные: +, -, *, /, max, min, div (целочисленное деление), abs (абсолютное значение), float (преобразование в тип float), integer (преобразование в тип integer)
•Расширенные: sqrt (извлечение корня), round (округление числа), mod (вычисление остатка от деления)
•Тригонометрические: sin, sinh, cos, cosh, tan, tanh, acos, acosh, acot, acoth, acsc, acsch, asec, asech, asin, asinh, atan, atanh, cot, coth, csc, csch, sec, sech, deg-grad (преобразование из градусов в секторы), deg-rad (преобразование из градусов в радианы), grad-deg (преобразование из секторов в градусы), rad-deg (преобразование из радиан в градусы)
Примеры фактов:
(voltage is 220 volt)
(meeting (subject "AI") (chief "Serp") (Room "№ 2"))
В первой строке приведен упорядоченный факт, во второй - неупорядоченный, в котором порядок слотов не важен.
Пример определения фактов:
(deftemplate person (slot name)
(slot age)
72
