- •Оглавление
- •Предисловие
- •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
- •Литература и Интернет-ресурсы
(defrule result
(declare (salience –1)) (initial-fact)
=>
(retract 0 ) (facts)
(save-facts “odessa”))
В CLIPS удаление факта выполняется командой retract с указанием индекса удаляемого факта либо переменной, с которой факт связывается. Значение индекса (целое число) факты получают автоматически при загрузке базы данных в интерпретатор или при их добавлении в уже загруженную базу. Системный начальный факт всегда имеет индекс "0". Связывание факта с переменной выполняется в LHS правила указателем "<–". Теперь все понятно.
Поясним только действия, выполняемые последним правилом. Вначале из рабочей памяти интерпретатора CLIPS удаляется initial-fact. Если это не сделать, программа зацикливается. Затем факты выводятся на стандартное устройство вывода (монитор). В последнем действии факты сохраняются в файле с именем odessa. Сохраним программа с этими правилами в файле odessa-only.clp. Затем, находясь в интерпретаторе CLIPS, загрузим его в дополнение к уже загруженным файлам rep и represent.clp и запустим на выполнение
CLIPS> (load odessa-only.clp)
. . . . . . . . . . . . . . .
TRUE
CLIPS> (run)
f-1 (rep Alejnov Odessa) f-2 (rep Ladak Odessa) f-6 (rep Pustovit Odessa) f-7 (rep Spokojnij Odessa) f-8 (rep Shamis Odessa) For a total of 5 facts
CLIPS>
В рассмотренном примере БЗ состоит из трех программных модулей. Однако, ничто не мешает использовать только одну программу сохраненную в одном файле.
1.6. Пример использования эвристического механизма представления знаний совместно с процедурным
Пусть требуется подобрать резистор для участка цепи электрической схемы некоторого устройства. Резистор характеризуется сопротивлением, которое определяется в соответствии с законом Ома по измеренным или рассчитанным значениям тока, проходящего через резистор, и падению
23
напряжения на нем. Программа с именем resistor.clp, решающая эту задачу, может быть, например, такой
(deffacts resistors |
; This is database |
(resistor Ra 2) |
|
(resistor Rb 5) |
|
(resistor Rc 7)) |
|
(deffunction om |
; This is function om(x,y) |
(?x ?y) |
|
(div ?y ?x)) |
|
(defrule input |
; This is current & strait input |
(initial-fact) |
|
=> |
|
(printout t crlf “Input current value: “) |
|
(bind ?i (read)) |
|
|
(printout t “Input strait |
value: “) |
|
(bind ?u (read)) |
|
|
(assert (numbers ?i ?u))) |
|
|
(defrule take |
; Get resistor from database |
|
(numbers ?i ?u) (resistor ?r =(om ?i ?u)) =>
(printout t crlf “You must take resistor “ ?r”.” crlf crlf)
(reset)
(halt))
(defrule nothing |
; There is nothing |
(numbers ?i ?u) |
|
(resistor ?r ~=(om ?i ?u)) |
|
=> |
|
(printout t crlf “There is nothing in my database!”
crlf crlf)
(reset)
(halt))
Программа состоит из пяти частей: базы данных с именем resistors, объявления пользовательской функции om и трех правил с именами input, take и nothing.
В базе данных содержатся сведения о резисторах. Они представлены в виде списков, которые состоят из трех полей. Первое поле имеет значение resistor и отражает тип радиодетали. Во втором поле списка содержится тип резистора. Последнее поле хранит значение сопротивления.
Офункции om говорилось ранее. Она представляет процедурное знание
озаконе Ома. Деление нацело — исключительно для упрощения.
24
Правило input предназначено для ввода данных. Оно активизируется системным начальным фактом и требует от пользователя ввести ток и напряжение. Встроенная функция read возвращает значение, введенное со стандартного устройства ввода (клавиатуры), которое сохраняется в переменных ?i и ?u. В RHS правила выполняется еще одно действие. Команда assert добавляет в рабочую память интерпретатора CLIPS факт (numbers ?i ?u). Для чего? Для того чтобы можно было обращаться к локальным переменным ?i и ?u, связанным с правилом input, из других правил программы.
Вследующих двух правилах пользователю либо предлагается тип подходящего резистора (правило take), либо сообщается, что таковой отсутствует (правило nothing).
Рассмотрим правило take. Его LHS состоит из двух условий, поэтому правило активизируется, если оба условия будут удовлетворены. Первое условие удовлетворяется, т.к. соответствующий факт уже создан правилом input. Второе условие удовлетворится, если будет точно соответствовать какому-либо факту (списку) в базе данных. Первое поле условия вопросов не вызывает. Во втором поле условия находится переменная ?r, которая может принять значение Ra, либо Rb, либо Rc в зависимости от содержимого третьего поля условия. В этом поле осуществляется вызов функции om и сохраняется возвращаемое функцией значение. Так, если возвращаемое значение будет равно 7, то условие удовлетворится, переменная ?r примет значение Rc, правило активизируется и выведет на экран монитора предложение выбрать резистор Rc. Если возвращаемое функцией om значение равно 5, то пользователю будет предложен резистор
Rb и т.д.
ВLHS правила nothing вроде бы полная аналогия, за исключением одной маленькой модификации. В третьем поле второго условия перед вызовом функции om стоит символ "~" – это логическое отрицание. Таким образом, условие удовлетворится и правило активизируется, если возвращаемое функцией om значение будет не 2, не 5 и не 7.
Находясь в интерпретаторе CLIPS, командой (clear) очистим его от данных предыдущего примера, загрузим файл resistor.clp и запустим программу на выполнение. Получим нечто следующее:
CLIPS> (clear)
CLIPS> (load resistor.clp)
. . . . . . . . . . . . .
TRUE
CLIPS> (reset) CLIPS> (run)
Input current value: 3
Input strait value: 15
25
You must take resistor Rb.
CLIPS> (run)
Input current value: 3.5
Input strait value: 5.44
There is nothing for You in my database!
CLIPS>
Таким образом, файл resistor.clp также представляет собой базу знаний, т.к. содержит и базу данных, и сведения (правила) о том, как данные могут быть использованы. Эта база располагает, по крайней мере, тремя знаниями. Первое знание — общий список резисторов с указанием типа и сопротивления. Второе знание — закон Ома. Третье знание — предлагаемый тип резистора.
Интеллект базы знаний можно существенно повысить добавлением новых данных и правил. Так, вместо закона Ома можно использовать более серьезные методики определения сопротивления резистора, например, схемотехническую САПР PSpice. Результаты ее работы можно сохранить в текстовом файле, а затем вызвать из третьего поля второго условия правила take. Другой путь — добавление новых типов резисторов в базу данных. Например, интересный результат получается при внесении в базу данных записи (resistor Rd 2). При некоторой доработке правил take и nothing, если возвращаемое функцией om значение равно 2, правило take отработает два раза и предложит резисторы Ra и Rd. Затем можно пойти дальше — добавить правило (правила), которое выберет из резисторов Ra и Rd предпочтительный для некоторых конкретных условий и т.д. и т.д.
26
