【问题标题】:Rule for union of two different deftemplates两个不同定义模板的联合规则
【发布时间】:2019-12-10 16:40:27
【问题描述】:

我希望以前没有人问过这个问题,因为我试图搜索已经问过的问题。我正在尝试编写一个规则,该规则将检查一个 deftemplate 中定义的两个不同插槽是否都存在于不同 deftemplate 的多插槽中。例如:

(deftemplate manifest
    (slot origin (type SYMBOL))
    (slot destination (type SYMBOL))
    (slot pkgsize (type INTEGER))
    (slot priority (type INTEGER))
    (slot zone (type SYMBOL) (default UNKNOWN))
)   
(deftemplate shipzone
    (slot zonename (type SYMBOL))
    (multislot cities (type SYMBOL))
)

(deffacts load-data
    (manifest (origin CHI) (destination DET) (pkgsize 10) (priority 1))
    (manifest (origin ATL) (destination WAS) (pkgsize 8) (priority 2))
    (manifest (origin CHI) (destination WAS) (pkgsize 15) (priority 1))
    (shipzone (zonename ZONEA) (cities CHI DET NYC BOS))
    (shipzone (zonename ZONEB) (cities ATL WAS NYC))
    (shipzone (zonename ZONEC) (cities CHI WAS BOS))
)

(defrule city-group
    ?f <- (manifest (origin ?x1) (destination ?x2) (zone UNKNOWN))
    (shipzone (zonename ?zname) (cities $?x1 $?x2))
    =>
    (modify ?f (zone ?zname))
)

给出以下错误:

CLIPS> (clear)
CLIPS> (load testgroup.clp)

[ANALYSIS3] testgroup.clp, Line 29: Variable ?x1 is used as both a single and multifield variable in the LHS.

ERROR:
(defrule MAIN::city-group
   ?f <- (manifest (origin ?x1) (destination ?x2))
   (shipzone (zonename ?zname) (cities $?x1 $?x2))
   =>
   (modify ?f (zone ?zname)))
%%$*
FALSE
CLIPS>

我做错了什么,或者有更好的方法来解决这个问题?

【问题讨论】:

    标签: clips


    【解决方案1】:

    在模式中绑定变量时,必须始终绑定到单字段或多字段变量。当您最初在 ma​​nifest 模式中绑定单变量 ?x1 和 ?x2 时,它们被绑定到一个值。当您在 shipzone 模式中绑定多字段变量 $?x1$?x2 时,它们将被绑定到零个或多个值。因为绑定在多个地方的变量必须具有相同的值,所以如果规则匹配,$?x1$?x2 不可能有多个值,所以这个被视为错误,因为该模式不太可能按照您的想法执行。

    您可以通过多种方式重写此规则。如果您希望 cities 槽以 origin 开头,并以 destination 结尾,中间有任意数量的城市,您需要重写您的规则这种方式使用多字段通配符跳过中间城市:

    (defrule city-group
        ?f <- (manifest (origin ?x1) (destination ?x2) (zone UNKNOWN))
        (shipzone (zonename ?zname) (cities ?x1 $? ?x2))
        =>
        (modify ?f (zone ?zname))
    )
    

    如果城市可以在 origin 之前或在 destination 之后,您可以这样重写您的规则:

    (defrule city-group
        ?f <- (manifest (origin ?x1) (destination ?x2) (zone UNKNOWN))
        (shipzone (zonename ?zname) (cities $? ?x1 $? ?x2 $?))
        =>
        (modify ?f (zone ?zname))
    )
    

    最后,如果您想检查 origindestination 是否包含在 cities 插槽中(包括 >destination 出现在 origin 之前),你可以这样重写你的规则:

    (defrule city-group
        ?f <- (manifest (origin ?x1) (destination ?x2) (zone UNKNOWN))
        (shipzone (zonename ?zname) (cities $?cities))
        (test (and (member$ ?x1 ?cities)
                   (member$ ?x2 ?cities)))
        =>
        (modify ?f (zone ?zname))
    )
    

    test 条件元素中,member$ 函数被传递变量 ?cities 而不是 $?cities (尽管两者都可以)。这是允许的,因为变量不受此用途的约束。变量的值只是被传递给函数。

    【讨论】:

    • 谢谢。第三个选项是我的确切用例。
    猜你喜欢
    • 2015-08-21
    • 2021-07-24
    • 1970-01-01
    • 1970-01-01
    • 2014-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多