首页 > 解决方案 > CLIPS 如何根据 deftemplate 关系槽查找事实

问题描述

我正在使用deftemplates. deffacts family我通过断言人们的母亲和父亲来声明最初的事实基础。然后我设置了一堆规则来断言兄弟姐妹、祖父母、堂兄弟等。我想从用户那里得到两个名字,然后根据事实,它会告诉我他们之间的关系是什么。我被这个问题难住了,请帮忙。

我一直在尝试使用find-all-factsfind-fact但我不知道如何正确使用查询语法。我需要一个循环来遍历每个事实吗?

我正在使用的deftemplates:

(deftemplate father-of   (slot father)  (slot child))
(deftemplate mother-of   (slot mother)  (slot child))
(deftemplate parent-of  (slot parent)   (slot child))
(deftemplate sister-of  (slot sister)   (slot sibling))
(deftemplate brother-of (slot brother)  (slot sibling))
(deftemplate aunt-of    (slot aunt)     (slot nephew-or-niece))
(deftemplate uncle-of   (slot uncle)    (slot nephew-or-niece))
(deftemplate cousin-of  (slot cousin-1) (slot cousin-2))
...

最初的事实基础被剪断:

(deffacts family
    ;GreatGrandParents
    (father-of (father "Henry") (child "Bob"))
    (father-of (father "Henry") (child "Susie"))
    (father-of (father "Henry") (child "Anton"))
    (mother-of (mother "Georgette") (child "Bob"))
    ...)

我一直在尝试的:

(defrule get-relationship ""
    =>
    (printout t crlf "Enter a person in the family: ")
    (bind ?p1 (read))
    (printout t crlf "Enter another person in the family: ")
    (bind ?p2 (read))
    (find-all-facts
        ($a?-of ($a? ?p1) ($b? ?p2))               ;any fact that contains both names entered
        ((!= 0 (str-compare ?p1 ?p2))              ;given ?p1 and ?p2 are dissimilar
        (printout t ?p1 "is a" $a? "of" $b? crlf)) ;display the relationship found
)

标签: clipsexpert-system

解决方案


使用查询:

         CLIPS (6.31 6/12/19)
CLIPS> 
(deftemplate of
   (slot relation)
   (slot p1)
   (slot p2))
CLIPS> 
(deffacts family
   (of (relation father) (p1 "Henry") (p2 "Bob"))
   (of (relation father) (p1 "Henry") (p2 "Susie"))
   (of (relation father) (p1 "Henry") (p2 "Anton"))
   (of (relation mother) (p1 "Georgette") (p2 "Bob")))
CLIPS>    
(defrule get-relationship ""
    =>
    (printout t "Enter a person in the family: ")
    (bind ?p1 (readline))
    (printout t "Enter another person in the family: ")
    (bind ?p2 (readline))
    (do-for-all-facts ((?o of)) 
       (and (eq ?p1 ?o:p1)
            (eq ?p2 ?o:p2))
       (printout t ?p1 " is a " ?o:relation " of " ?p2 crlf)))
CLIPS> (reset)
CLIPS> (run)
Enter a person in the family: Henry
Enter another person in the family: Susie
Henry is a father of Susie
CLIPS>

使用模式:

CLIPS> (clear)
CLIPS> 
(deftemplate of
   (slot relation)
   (slot p1)
   (slot p2))
CLIPS> 
(deftemplate find
   (slot p1)
   (slot p2))
CLIPS>   
(deffacts family
   (of (relation father) (p1 "Henry") (p2 "Bob"))
   (of (relation father) (p1 "Henry") (p2 "Susie"))
   (of (relation father) (p1 "Henry") (p2 "Anton"))
   (of (relation mother) (p1 "Georgette") (p2 "Bob")))
CLIPS>    
(defrule get-find ""
    =>
    (printout t "Enter a person in the family: ")
    (bind ?p1 (readline))
    (printout t "Enter another person in the family: ")
    (bind ?p2 (readline))
    (assert (find (p1 ?p1) (p2 ?p2))))
CLIPS>     
(defrule get-relationship
   (find (p1 ?p1) (p2 ?p2))
   (of (relation ?relation) (p1 ?p1) (p2 ?p2))
   =>
   (printout t ?p1 " is a " ?relation " of " ?p2 crlf)))
CLIPS> 
(defrule done-find ""
    (declare (salience -10))
    ?f <- (find)
    =>
    (retract ?f))
CLIPS> (reset)
CLIPS> (run)
Enter a person in the family: Georgette
Enter another person in the family: Bob
Georgette is a mother of Bob
CLIPS>

推荐阅读