我们可以在Jess中计算具有相同值的事实吗?

时间:2012-02-12 01:35:38

标签: expert-system jess

使用Jess作为规则引擎,我们可以断言一个事实,即某个证人在某个地方看到过一个人,并且与时间有关:

(deffacts witnesses
    (witness Batman Gotham 18)
    (witness Hulk NYC 19)
    (witness Batman Gotham 2)
    (witness Superman Chicago 22)
    (witness Batman Gotham 10)
)

根据规则,我想知道是否有多位证人在同一个地方见过同一个人,而不是考虑时间。

在Jess文档中,我们得到了这个示例,用于计算制作100K及以上的管理员的员工:

(defrule count-highly-paid-employees
    ?c <- (accumulate (bind ?count 0)                        ;; initializer
    (bind ?count (+ ?count 1))                    ;; action
    ?count                                        ;; result
    (employee (salary ?s&:(> ?s 100000)))) ;; CE
    =>
    (printout t ?c " employees make more than $100000/year." crlf))

所以我的代码基于前面的例子:

(defrule count-witnesses
    (is-lost ?plost)
    (witness ?pseen ?place ?time)
    ?c <- (accumulate (bind ?count 0)
    (bind ?count (+ ?count 1))
    ?count
    (test ())  ; conditional element of accumulate
    (test (= ?plost ?pseen))
    (test (>= ?count 3))
    =>
    (assert (place-seen ?place))
)

使用上面提供的'(deffacts)'指令和规则,引擎应断言事实

(place-seen Gotham)

因为我们在Gotham看过三次蝙蝠侠。

我不知道如何使用'accumulate'的条件元素(CE)部分。我可以使用“测试”来保留同一个人和地点的事实吗?

知道如何实现这个目标吗?

谢谢!


注意:'accumulate'的synthax是

(accumulate <initializer> <action> <result> <conditional element>)

1 个答案:

答案 0 :(得分:1)

我将遗漏关于?plost的内容,因为你没有解释那是什么,确切地说;如果需要,你可以把它添加回来。

(几乎)做你想要的基本规则如下。你没有得到的CE部分只是我们想要积累的模式;在这里,它与在同一地点见证的同一人匹配事实,与第一人匹配的事实相符:

(defrule count-witnesses
  ;; Given that some person ?person was seen in place ?place
  (witness ?person ?place ?)  
  ;; Count all the sightings of that person in that place  
  ?c <- (accumulate (bind ?count 0)
                    (bind ?count (+ ?count 1))
                    ?count
                    (witness ?person ?place ?))
  ;; Don't fire unless the count is at least 3
  (test (>= ?c 3))
  =>
  (assert (place-seen ?person ?place))
)

现在,这个规则的唯一问题是它会为你的deffacts发射三次,每次蝙蝠侠/高谭事实都会发射一次。我们可以通过改变第一个模式来阻止这一点,以便只匹配某个地方最早的人物:

(defrule count-witnesses
  ;; Given that some person ?person was seen in place ?place, and there is no other 
  ;; sighting of the same person at the same place at an earlier time
  (witness ?person ?place ?t1)    
  (not (witness ?person ?place ?t2&:(< ?t2 ?t1)))
  ;; Count all the sightings of that person in that place  
  ?c <- (accumulate (bind ?count 0)
                    (bind ?count (+ ?count 1))
                    ?count
                    (witness ?person ?place ?))
  ;; Don't fire unless the count is at least 3
  (test (>= ?c 3))
  =>
  (assert (place-seen ?person ?place))
)