让我们考虑下一个简单的模板:
(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))
但它不起作用。
我怎么能做到这样的事情?
默认情况下,您无法创建重复的事实:
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>