两个不同 detemplates 的合并规则
Rule for union of two different deftemplates
我希望以前没有人问过这个问题,因为我试图搜索已经问过的问题。我正在尝试编写一个规则来检查一个 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>
我做错了什么,或者有更好的方法来解决这个问题吗?
在模式中绑定变量时,必须一致地绑定到单字段或多字段变量。当您最初在 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))
)
最后,如果您想检查 origin 和 destination 是否包含在 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(尽管两者都可以)。这是允许的,因为变量不受此用途的约束。变量的值只是传递给函数。
我希望以前没有人问过这个问题,因为我试图搜索已经问过的问题。我正在尝试编写一个规则来检查一个 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>
我做错了什么,或者有更好的方法来解决这个问题吗?
在模式中绑定变量时,必须一致地绑定到单字段或多字段变量。当您最初在 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))
)
最后,如果您想检查 origin 和 destination 是否包含在 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(尽管两者都可以)。这是允许的,因为变量不受此用途的约束。变量的值只是传递给函数。