Проверить, существует ли факт со значением поля мультиполя в клипах

#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-from , так и stops-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))
  

Приведенное выше правило проверяет только допустимость станции отправления, как мне проверить, существуют ли обе станции отправления и каждая станция остановки?

Ответ №1:

Самое простое, что можно сделать, это иметь отдельные правила, которые проверяют станции отправления и остановки и срабатывают каждый раз, когда обнаруживается неизвестная станция. Если вы хотите, чтобы одно сообщение печаталось независимо от количества неизвестных станций, добавьте слот идентификатора к каждому факту поезда, чтобы вы могли писать более сложные шаблоны, которые будут совпадать только один раз для каждого поезда.

          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>