Шаблоны и условия
Возвращаясь к элементу test, можно утверждать, что его использование позволяет проверить что-то в левой части правила, и не только факты. Так, можно написать правило, которое проверяет факт, что 6 больше, чем 5: Такое представление о множестве отдельных фактов, привязанных к именам персон, ничего не говорит о связях между ними. Лучший способ — использование стуктуры def template, например таким… Читать ещё >
Шаблоны и условия (реферат, курсовая, диплом, контрольная)
Правила и факты, хотя и обладают большой гибкостью, нс позволяют решать все задачи. CLIPS предлагает также полный набор функций процедурного программирования. Далее рассмотрим шаблоны и условия, позволяющие реализовать такое программирование.
Рассмотрим пример, в котором нужно определить общий фитнесс множества людей. Здесь должны быть использованы для различных персон (Andrew и Brenda) разные индикаторы. Можно отобразить информацию об этих персонах так:
- (age Andrew 20)
- (weight Andrew 80)
- (height Andrew 188)
- (blood-pressure Andrew 130 80)
- (age Brenda 23)
- (weight Brenda 50)
- (height Brenda 140)
- (blood-pressure Brenda 120 60)
Такое представление о множестве отдельных фактов, привязанных к именам персон, ничего не говорит о связях между ними. Лучший способ — использование стуктуры def template, например таким образом:
- (deftemplate personal-data (slot name)
- (slot age)
- (slot weight)
- (slot height)
- (multislot blood-pressure)
).
Здесь deftemplate не создает факты, но формирует для них структуру. Каждый раз, когда создается факт этого типа, он содержит слоты, специфицированные в этой информации, каждый из которых содержит значение и может быть связан с именем. Данные о каждой персоне теперь могут быть введены так:
(assert (personal-data (name Andrew) (age 20) (weight 80) (height 188) (blood-pressure 130 80))).
или так, в стуктуре def facts:
- (deffacts people
- (personal-data (name Andrew) (age 20) (weight 80)
- (height 188) (blood-pressure 130 80))
- (personal-data (name Cyril) (age 63) (weight 70)
- (height 1678) (blood-pressure 180 90)))
При этом не нужно специфицировать всю информацию, поскольку она совершенно валидна:
(assert (personal-data (weight 150) (age 23) (name Brenda))).
Порядок, в котором используются слоты, не имеет значения, поскольку ссылки на них производятся по имени. Это позволяет также установить несколько из них, если это нужно. Факты-шаблоны могут быть изменены без их удаления и добавления новой версии. Функция modify позволяет изменить значение одного или более слотов в факте.
Предположим, что у Андрея день рождения. Если определить правило.
- (defrule birthday
- ?birthday <- (birthday ?name)
- ?data-fact <- (personal-data (name ?name) (age ?age))
=>
- (modify ?data-fact (age (+ ?age 1)))
- (retract ?birthday)
).
то добавление факта (birthday Andrew) модифицирует возраст Андрея, в то время как все его другие персональные данные останутся. Отметим, что причина удаления факта дня рождения — поддержание истинности. День рождения Андрея имеет место только один раз в год, и если оставить этот факт в базе, то он вскоре должен стать ложным. Так, каждый раз, когда персональные данные Андрея (вес, например) изменяются, правило дня рождения должно быть запущено, вызывая изменение возраста.
Факты-шаблоны могут быть использованы в правилах только как ординарные факты, например, так:
- (defrule lardy-bugger
- (personal-data (name ?name) (weight ?weight))
- (test (> ?weight 100))
=>
(printout t? name «weighs » ?weight «kg — the fat sod.».
crlf).
).
В этом правиле введен также условный элемент (test (> ?weight 100)). Он позволяет сделать в левой части правила определенное количество сравнений для оценки значения параметра. В этом случае будут сопоставляться факты, где значение веса weight в слоте больше чем 100 кг.
Имеется несколько способов использования условных элементов в правилах. Первый — использование неявного логического оператора AND между двумя паттернами в левой части правила, например:
- (defrule print-ages
- (personal-data (name ?name) (age ?age))
=>
(printout t? name «is » ?age «years old.» crlf).
).
Это правило имеет следующий смысл: «Если имеется факт с именем и возрастом, то вывести его на принтер». Связка AND может быть также использована явно таким образом:
- (defrule print-ages (and
- (personal-data (name ?name) (age ?age))
- (personal-data (name ?name) (weight ?weight))
).
=>
(printout t? name «weighs » ?weight «at » ?age «years.
old." crlf).
Хотя в приведенном примере связка AND лишняя, она, как будет видно далее, является очень полезной в более сложных логических конструкциях. Можно также использовать связку OR таким образом:
- (defrule take-an-umbrella (or
- (weather raining)
- (weather snowing)
).
=>
(printout t «Take an umbrella» crlf).
).
Это правило означает: «Если идет снег или дождь, нужно взять зонтик». Заметим, что OR и AND являются префиксными операторами, поэтому можно писать (or (thingl) (thing2)), а не ((thing) or (thing2)). Введенный здесь оператор традиционной логики NOT просто делает предикат негативным, например:
- (defrule not-birthday
- (personal-data (name ?name) (weight ?weight))
- (not (birthday ?name))
=>
(printout t «It's not » ?name «'s birthday» crlf).
).
Возвращаясь к элементу test, можно утверждать, что его использование позволяет проверить что-то в левой части правила, и не только факты. Так, можно написать правило, которое проверяет факт, что 6 больше, чем 5:
(defrule pointless (test (> 6 5)).
=>
(printout t «Six is indeed greater than five» crlf).
).
Используются также условные элементы exists и forall. Первый из них удовлетворяется, если имеется один или более фактов, которые сопоставляются с его предикатом; правило, содержащее его, запускается только один раз, вне зависимости от того, как много фактов сопоставляется. Элемент forall, с другой стороны, срабатывает один раз, если факт сопоставляется с его паттерном.
Так, два следующих правила вводят в базу фактов персональные данные нескольких персон:
- (defrule person-exists
- (personal-data (name ?name))
=>
(printout t «Rule person exists reports there is a person called » ?name crlf).
).
- (defrule are-there-people
- (exists (personal-data (name ?name)))
=>
(printout t «Rule are-there-people reports there is at least one person» crlf).
).
- (defrule check-each-person
- (forall (personal-data (name ?name))
- (
).
=>
(printout t «Rule check-each-person reports that all persons have a name» crlf).
).
Теперь можно создать новую персону без имени и запустить их снова. Третье правило check-each-person нс будет запускаться, потому что оно не является истинным для всех фактов, которые сопоставляются с этим паттерном.
Таким образом, в этой части описания были представлены фактышаблоны и условные элементы в следующем виде:
- (deftemplate (slot slotnamel) (slot slotnamel))
- (and (predicatel) (predicate2))
- (or (predicatel) (predicate2))
- (not (predicatel))
- (test (predicatel))
- (exists (pattern))
- (forall (patternl)
- (pattern2)