0

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

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

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

在 Jess 文档中,我们得到了这个示例,用于计算年薪超过 10 万的员工:

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

因为我们在哥谭见过蝙蝠侠三遍。

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

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

谢谢!


注意:'accumulate' 的语法是

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

1 回答 1

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

现在,这条规则的唯一问题是它会为你的 触发 3 次deffacts,每一个 Batman/Gotham 事实触发一次。我们可以通过更改第一个模式以仅匹配给定地点最早看到的人来阻止这种情况:

(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))
)
于 2012-02-12T19:37:40.040 回答