片段:检查多个事实

时间:2019-03-20 19:28:32

标签: clips

让我们考虑下一个简单的模板:

(deftemplate person (ssn ?s))

我要检查的是,如果一个人“被注册”,那么没有其他人拥有相同的ssn,但是,我已经尝试过类似的操作:

(defrule repeated-person
     (person (ssn ?s1))
     (person (ssn ?s2))
     (test (= ?s1 ?s2))
  =>
     (printout t "No, no, no..." clrf))

甚至

(defrule repeated-person
     (person (ssn ?s))
     (person (ssn ?s))
  =>
     (printout t "No, no, no..." clrf))

但是没有用。

我该怎么做?

1 个答案:

答案 0 :(得分:1)

默认情况下,您无法创建事实重复项:

         CLIPS (6.31 2/3/18)
CLIPS> 
(deftemplate person
   (slot SSN))
CLIPS> (assert (person (SSN 123-45-6789)))
<Fact-1>
CLIPS> (facts)
f-0     (initial-fact)
f-1     (person (SSN 123-45-6789))
For a total of 2 facts.
CLIPS> (assert (person (SSN 123-45-6789)))
FALSE
CLIPS> (facts)
f-0     (initial-fact)
f-1     (person (SSN 123-45-6789))
For a total of 2 facts.
CLIPS> 

您可以使用set-fact-duplication函数更改此行为:

CLIPS> (set-fact-duplication TRUE)
FALSE
CLIPS> (assert (person (SSN 123-45-6789)))
<Fact-2>
CLIPS> (facts)
f-0     (initial-fact)
f-1     (person (SSN 123-45-6789))
f-2     (person (SSN 123-45-6789))
For a total of 3 facts.
CLIPS>

然后,您可以编写一条规则来检查同一SSN是否存在两个不同的事实:

CLIPS> 
(defrule repeated-person
   ?f1 <- (person (SSN ?ss))
   ?f2 <- (person (SSN ?ss))
   (test (< (fact-index ?f1) (fact-index ?f2)))
   =>
   (printout t "Duplicated SSN " ?ss crlf))
CLIPS> (agenda)
0      repeated-person: f-1,f-2
For a total of 1 activation.
CLIPS>

由于每个事实都有唯一的事实索引,因此测试条件元素中的比较可确保与第一和第二模式匹配的事实不相同。

如果我们添加另一个具有相同SSN的人,我们将获得规则的多次激活:

CLIPS> (assert (person (SSN 123-45-6789)))
<Fact-3>
CLIPS> (agenda)
0      repeated-person: f-1,f-3
0      repeated-person: f-2,f-3
0      repeated-person: f-1,f-2
For a total of 3 activations.
CLIPS>

我们可以为每个创建的事实动态分配唯一的ID,即使禁用事实复制,该事实也允许创建“重复的”事实:

CLIPS> (clear)
CLIPS> (set-fact-duplication FALSE)
TRUE
CLIPS> 
(deftemplate person
   (slot id (default-dynamic (gensym*)))
   (slot SSN))
CLIPS> (assert (person (SSN 123-45-6789)))
<Fact-1>
CLIPS> (assert (person (SSN 123-45-6789)))
<Fact-2>
CLIPS> (assert (person (SSN 123-45-6789)))
<Fact-3>
CLIPS> (facts)
f-0     (initial-fact)
f-1     (person (id gen1) (SSN 123-45-6789))
f-2     (person (id gen2) (SSN 123-45-6789))
f-3     (person (id gen3) (SSN 123-45-6789))
For a total of 4 facts.
CLIPS>

然后我们可以创建一个规则,该规则将打印一条消息,而不考虑具有相同SSN的人数:

CLIPS> 
(defrule repeated-person
   (person (id ?id) (SSN ?ssn))
   (not (person (id ?id2&:(< (str-compare ?id2 ?id) 0)) (SSN ?ssn)))
   (exists (person (id ~?id) (SSN ?ssn)))
   =>
   (printout t "Duplicated SSN " ?ssn crlf))
CLIPS> (agenda)
0      repeated-person: f-1,*,*
For a total of 1 activation.
CLIPS> (run)
Duplicated SSN 123-45-6789
CLIPS>