Каков синтаксис для чтения значения слота объекта, где этот объект является переменной, и внутри defrule? - PullRequest
0 голосов
/ 08 октября 2019

Я копался в документации и не мог найти решение, поэтому прости меня, если я где-то пропустил это. Вот моя проблема: у меня есть два экземпляра класса PART, part1 и part2, а класс PART имеет слот с именем hasPort. Я хочу правило, которое совпадает на две части, если порты подключены. Каждый порт является экземпляром класса PORT, в котором есть слот с именем «connectedTo», который используется для хранения подключаемого экземпляра PORT.

Сначала мои объекты класса:

(defclass PART  (is-a USER)
   (role concrete)
   (slot affectsProperty (type INSTANCE))
   (slot directlyConnected (type INSTANCE))
   (slot hasPort (type INSTANCE))
   (slot hasSensor (type INSTANCE))
   (slot hasIssue (type INSTANCE))
   (multislot secondary-types))

(defclass PORT  (is-a USER)
   (role concrete)
   (slot connectedTo (type INSTANCE))
   (multislot secondary-types))

Я пыталсяправила вроде следующего:

(defrule rule0
   ?part1 <- (object (is-a PART) (hasPort ?port1))
   ?part2 <- (object (is-a PART) (hasPort ?port2))
   ?port1 <- (object (is-a PORT) (connectedTo ?port2))
   =>  
   ;(assert (directlyConnected ?part1 ?part2))
   (printout t "Found connected parts "
     (instance-name ?part1) " "
     (instance-name ?part2) " by ports "
     (instance-name ?port1) " "
     (instance-name ?port2)
     crlf))

Я также пробовал что-то вроде следующего:

(defrule rule0
   ?part1 <- (object (is-a PART) (hasPort ?port1))
   ?part2 <- (object (is-a PART) (hasPort ?port2))
   ?port2 <- (send ?port1 get-connectedTo)
   =>  
   ;(assert (directlyConnected ?part1 ?part2))
   (printout t "Found connected parts "
     (instance-name ?part1) " "
     (instance-name ?part2) " by ports "
     (instance-name ?port1) " "
     (instance-name ?port2)
     crlf))

и даже что-то вроде следующего:

(defrule rule0
   ?part1 <- (object (is-a PART) (hasPort ?port1))
   ?part2 <- (object (is-a PART) (hasPort ?port2))
   ?port3 <- (send ?port1 get-connectedTo)
   (test (eq ?port3 ?port2))
   =>  
   ;(assert (directlyConnected ?part1 ?part2))
   (printout t "Found connected parts "
     (instance-name ?part1) " "
     (instance-name ?part2) " by ports "
     (instance-name ?port1) " "
     (instance-name ?port2)
     crlf))

Кроме того, что являетсявозможно, если вы расскажете, какой подход является наиболее «естественным» способом написания этого правила, это было бы очень полезно.

1 Ответ

1 голос
/ 08 октября 2019

Ваше первое правило будет работать, если вы поместите третий шаблон первым, чтобы переменная ? Port1 была привязана к адресу экземпляра, прежде чем на нее будет ссылаться слот hasPort .

         CLIPS (6.31 6/12/19)
CLIPS> 
(defclass PART  (is-a USER)
   (role concrete)
   (slot affectsProperty (type INSTANCE))
   (slot directlyConnected (type INSTANCE))
   (slot hasPort (type INSTANCE))
   (slot hasSensor (type INSTANCE))
   (slot hasIssue (type INSTANCE))
   (multislot secondary-types))
CLIPS> 
(defclass PORT  (is-a USER)
   (role concrete)
   (slot connectedTo (type INSTANCE))
   (multislot secondary-types))
CLIPS>    
(defrule rule0
   ?port1 <- (object (is-a PORT) (connectedTo ?port2))
   ?part1 <- (object (is-a PART) (hasPort ?port1))
   ?part2 <- (object (is-a PART) (hasPort ?port2))
   =>  
   (printout t "Found connected parts "
     (instance-name ?part1) " "
     (instance-name ?part2) " by ports "
     (instance-name ?port1) " "
     (instance-name ?port2)
     crlf))
CLIPS> (make-instance port2 of PORT)
[port2]
CLIPS> (make-instance port1 of PORT (connectedTo (instance-address [port2])))
[port1]
CLIPS> (make-instance part1 of PART (hasPort (instance-address [port1])))
[part1]
CLIPS> (make-instance part2 of PART (hasPort (instance-address [port2])))
[part2]
CLIPS> (run)
Found connected parts [part1] [part2] by ports [port1] [port2]
CLIPS>

Вместо того, чтобы использовать адреса экземпляров для значений слотов, вы можете связать экземпляры вместе, используя имена экземпляров вместе с предопределенным name слотом для каждого экземпляра.

CLIPS> (clear)
CLIPS> 
(defclass PART  (is-a USER)
   (role concrete)
   (slot affectsProperty (type INSTANCE-NAME))
   (slot directlyConnected (type INSTANCE-NAME))
   (slot hasPort (type INSTANCE-NAME))
   (slot hasSensor (type INSTANCE-NAME))
   (slot hasIssue (type INSTANCE-NAME))
   (multislot secondary-types))
CLIPS> 
(defclass PORT  (is-a USER)
   (role concrete)
   (slot connectedTo (type INSTANCE-NAME))
   (multislot secondary-types))
CLIPS>    
(defrule rule0
   (object (is-a PART) (name ?part1) (hasPort ?port1))
   (object (is-a PART) (name ?part2) (hasPort ?port2))
   (object (is-a PORT) (name ?port1) (connectedTo ?port2))
   =>  
   (printout t "Found connected parts " ?part1 " " ?part2 
               " by ports " ?port1 " " ?port2 crlf))
CLIPS> (make-instance port1 of PORT (connectedTo [port2]))
[port1]
CLIPS> (make-instance port2 of PORT)
[port2]
CLIPS> (make-instance part1 of PART (hasPort [port1]))
[part1]
CLIPS> (make-instance part2 of PART (hasPort [port2]))
[part2]
CLIPS> (run)
Found connected parts [part1] [part2] by ports [port1] [port2]
CLIPS> 
...