两个不同deftemplate的并集规则

问题描述 投票:0回答:1

我希望在我尝试搜索已经提出的问题之前没有问过这个问题。我正在尝试编写一条规则,该规则将检查在一个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个回答
0
投票

当您在模式中绑定变量时,必须始终绑定到单字段或多字段变量。当您最初以manifest模式绑定单变量?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))
)

如果城市可以在来源之前或在目的地之后,您可以通过以下方式重写规则:

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

最后,如果要检查cities插槽中是否包含origindestination(包括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(尽管两者都可以)。这是允许的,因为变量不受此用法的限制。变量的值只是传递给函数。
© www.soinside.com 2019 - 2024. All rights reserved.