没有无限循环的CLIPS递增变量

CLIPS incrementing variable without endless loop

非常感谢对我的 CLIPS 项目的帮助。

好的,我正在尝试创建一个犬种顾问。 deftemplate 看起来像这样:

(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))

defacts 看起来像这样:

(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))

所以我写了两种类型的 defrules:一种收回不符合(用户指定的)标准的事实,另一种类型在每次事实符合标准时递增 "score" 值。只有少数规则会收回,所以让增量规则起作用对我来说很重要。每个插槽的用户输入和条件可以是 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)事实的唯一目的是增加分数并且在分数增加后不再需要,只需撤回该事实。

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

请注意,我已经从包含 ?通配符,因为这些是不必要的。

如果其他规则需要(输入 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)))

您还可以跟踪您在事实中的得分。添加一个(多槽得分)到你的品种 detemplate 然后你可以这样做:

(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))