Инкремент переменной CLIPS без бесконечного цикла

Я был бы очень признателен за помощь с моим проектом CLIPS.

Итак, я пытаюсь создать консультанта по породе собак. Дефемплет выглядит так:

(deftemplate breed
     (multislot name)
     (slot size)
     (slot type-owner)
     (slot Living_Space)
     (slot children)
     (slot grooming)
     (slot exercise)
     (slot noisiness)
     (slot trainability)
     (slot aggression)
     (slot playfulness)
     (slot excitability)
     (slot score))

Дефицит выглядит так:

(deffacts dog-breeds
(breed (name Great_Dane)
       (size 5)
       (type-owner No)
       (Living_Space 5)
       (children 5) 
       (grooming 1)
       (exercise 4)
       (noisiness 2)
       (trainability 1)
       (aggression 2)
       (playfulness 2)
       (excitability 3)
       (score 0))

Таким образом, я пишу два типа отклонений: один отводит факты, которые не соответствуют (указанным пользователем) критериям, а другой тип увеличивает значение "оценки" каждый раз, когда факт соответствует критериям. Только несколько правил убираются, поэтому для меня важно, чтобы правила приращения работали. Пользовательский ввод и критерии для каждого слота могут быть от 1 до 5.

Мой вопрос: как мне изменить следующий код, не переходя в бесконечный цикл? В конце я хочу найти факт с максимальным счетом и отобразить его.

(defrule children
(input 1)
?children <- (breed (name ?)(size ?)(type-owner ?)(Living_Space  ?)   (children 1|2)(grooming ?)(exercise ?)(noisiness ?)
(trainability ?)(aggression ?)(playfulness ?)(excitability ?)(score  ?score)
=>  
(bind ?sc (+ ?score 1))
(modify ?children (score ?sc))

1 ответ

Решение

Если единственная цель факта (вход 1) состоит в увеличении оценки и больше не нужна после увеличения оценки, просто уберите этот факт.

(defrule children
   ?f <- (input 1)
   ?children <- (breed (children 1|2) (score ?score))
   =>
   (retract ?f)  
   (bind ?sc (+ ?score 1))
   (modify ?children (score ?sc)))

Обратите внимание, что я удалил все слоты из шаблона, содержащего? подстановочный знак, поскольку они не нужны.

Если факт (input 1) необходим по другим правилам, вы можете создать промежуточный факт, который можно отозвать.

(defrule create-intermediate
   (input 1)
   => 
   (assert (increment)))

(defrule children
   ?f <- (increment)
   ?children <- (breed (children 1|2) (score  ?score))
   =>
   (retract ?f)  
   (bind ?sc (+ ?score 1))
   (modify ?children (score ?sc)))

Вы также можете отслеживать, что вы набрали в этом факте. Добавьте (мультислот забитый) к вашей породе, и тогда вы можете сделать это:

(defrule children
   (input 1)
   ?children <- (breed (children 1|2) (score ?score) (scored $?scored))
   (test (not (member$ children ?scored)))
   =>
   (bind ?sc (+ ?score 1))
   (modify ?children (score ?sc) (scored children ?scored)))

Наконец, шаблоны объектов не запускаются повторно при изменении слотов, которые отсутствуют в шаблоне. Так что, если вы используете defclasses вместо deftemplates, вы можете сделать это:

(defrule children
   (input 1)
   ?children <- (object (is-a BREED) (children 1|2))
   =>
   (bind ?sc (+ (send ?children get-score) 1))
   (send ?children put-score ?sc))
Другие вопросы по тегам