测试 Clips 中是否存在字段值为 multifield 的事实

Test if a fact with a field value of a multifield exists in Clips

我有以下车站和火车的事实模板:

(deftemplate station
    (slot name (type SYMBOL))
    (slot status (type SYMBOL) (default open)))

(deftemplate train
    (slot departs-from (type SYMBOL))
    (multislot stops-at (type SYMBOL))) 

插槽 departs-fromstops-at 都引用了 name 个站点。

(deffacts trains-and-stations
    (station (name station-a))
    (station (name station-b))
    (station (name station-c))
    
    (train (departs-from station-a) (stops-at unknown-station))
    (train (departs-from station-a) (stops-at station-b station-c))
    (train (departs-from station-b) (stops-at station-c station-a)))

我想制定一个规则来测试每列火车中使用的车站事实是否存在:

(defrule check-valid-stations
    ?train <- (train (departs-from ?from) (stops-at $?stops))
    (not (exists (station (name ?from))))
    =>
    (printout t "Route of " $train " contains an unknown station!" crlf))

上面的规则只检查出发站是否有效,如何检查出发站和每个停靠站是否都存在?

最简单的做法是制定单独的规则来检查 departs-from 和 stops-at 站,并在每次发现未知站时触发。如果您希望无论未知车站的数量如何都打印一条消息,请向每个火车事实添加一个 id 插槽,以便您可以编写更复杂的模式,这些模式只会为每辆火车匹配一次。

         CLIPS (6.31 6/12/19)
CLIPS> 
(deftemplate station
    (slot name (type SYMBOL))
    (slot status (type SYMBOL) (default open)))
CLIPS> 
(deftemplate train
    (slot id)
    (slot departs-from (type SYMBOL))
    (multislot stops-at (type SYMBOL)))
CLIPS>     
(deffacts trains-and-stations
    (station (name station-a))
    (station (name station-b))
    (station (name station-c))
    
    (train (id 1) (departs-from station-a) (stops-at unknown-station))
    (train (id 2) (departs-from station-a) (stops-at station-b station-c))
    (train (id 3) (departs-from station-b) (stops-at station-c station-a))
    (train (id 4) (departs-from some-station) (stops-at station-c station-a bad-location)))
CLIPS>         
(defrule check-valid-stations-departs
    ?train <- (train (departs-from ?from))
    (not (station (name ?from)))
    =>
    (printout t "Route of " ?train " contains an unknown station: " ?from crlf))
CLIPS>     
(defrule check-valid-stations-stops
    ?train <- (train (stops-at $? ?to $?))
    (not (station (name ?to)))
    =>
    (printout t "Route of " ?train " contains an unknown station: " ?to crlf))
CLIPS>     
(defrule check-valid-stations
    ?train <- (train (id ?id) (departs-from ?from))
    (exists (or (not (station (name ?from)))
                (and (train (id ?id) (stops-at $? ?to $?))
                     (not (station (name ?to))))))
    =>
    (printout t "Route of " ?train " contains an unknown station!" crlf))
CLIPS> (reset)
CLIPS> (run)
Route of <Fact-7> contains an unknown station: some-station
Route of <Fact-7> contains an unknown station!
Route of <Fact-7> contains an unknown station: bad-location
Route of <Fact-4> contains an unknown station!
Route of <Fact-4> contains an unknown station: unknown-station
CLIPS>