使用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>)
答案 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))
)