如何优化 CLIPS 中不同模板化事实之间的模式匹配
How to optimize pattern matching between different templated facts in CLIPS
我有一个类似于以下的规则:
(deftemplate person
(slot name ( type INTEGER))
(slot surname ( type INTEGER))
)
(defrule surname_cant_be_a_name
?p1<-(person (name ?n1))
?p2<-(person (surname ?n2&:(= ?n1 ?n2)))
=>
(retract ?p2)
)
从功能上讲,这是有效的。但是我 运行 这是在一个巨大的事实集上进行的,而且复杂性很快就会达到顶峰。
因为规则正在寻找两个人对象,所以存在嵌套的 for 循环有点减慢执行速度的情况。此设置会遍历每个可能的人配对,只有在配对后,规则才会根据我的设置过滤掉“&:(= ?n1 ?n2))”
我觉得一定有更聪明的方法来做到这一点。理想情况下,我希望 p1 遍历所有 person 对象,但只匹配符合我规则的 p2 对象。
为了使我的观点更清楚,我正在寻找类似以下内容的东西,它可以避免双重循环:
(defrule surname_cant_be_a_name
?p1<-(person (name ?n1))
?p2<-(person (surname %%JUST_MATCH_n1%% ))
=>
(retract ?p2)
)
这有可能实现这样的目标吗?任何优化此规则的建议都将受到赞赏。
谢谢
P.S。抱歉这个荒谬的例子,但它很好地突出了我的情况。
如果要比较变量的相等性,在两个地方使用同一个变量比使用两个单独的变量并调用 = 或 eq 函数比较是否相等。在各种模式中,哈希表用于快速定位共享相同变量的事实,而当您使用函数调用来执行相等比较时则不会这样做。对于大量的事实,这可以提高几个数量级的性能:
CLIPS (6.31 6/12/19)
CLIPS> (clear)
CLIPS>
(deftemplate person
(slot name (type INTEGER))
(slot surname (type INTEGER)))
CLIPS>
(defrule surname_cant_be_a_name
?p1<- (person (name ?n1))
?p2<- (person (surname ?n2&:(= ?n1 ?n2)))
=>
(retract ?p2))
CLIPS> (timer (loop-for-count (?i 10000) (assert (person (name ?i) (surname (+ ?i 1))))))
12.3485549999987
CLIPS> (clear)
CLIPS>
(deftemplate person
(slot name (type INTEGER))
(slot surname (type INTEGER)))
CLIPS>
(defrule surname_cant_be_a_name
?p1 <- (person (name ?n1))
?p2 <- (person (surname ?n1))
=>
(retract ?p2))
CLIPS> (timer (loop-for-count (?i 10000) (assert (person (name ?i) (surname (+ ?i 1))))))
0.0177029999995284
CLIPS> (/ 12.3485549999987 0.0177029999995284)
697.540247434201
CLIPS>
我有一个类似于以下的规则:
(deftemplate person
(slot name ( type INTEGER))
(slot surname ( type INTEGER))
)
(defrule surname_cant_be_a_name
?p1<-(person (name ?n1))
?p2<-(person (surname ?n2&:(= ?n1 ?n2)))
=>
(retract ?p2)
)
从功能上讲,这是有效的。但是我 运行 这是在一个巨大的事实集上进行的,而且复杂性很快就会达到顶峰。
因为规则正在寻找两个人对象,所以存在嵌套的 for 循环有点减慢执行速度的情况。此设置会遍历每个可能的人配对,只有在配对后,规则才会根据我的设置过滤掉“&:(= ?n1 ?n2))”
我觉得一定有更聪明的方法来做到这一点。理想情况下,我希望 p1 遍历所有 person 对象,但只匹配符合我规则的 p2 对象。
为了使我的观点更清楚,我正在寻找类似以下内容的东西,它可以避免双重循环:
(defrule surname_cant_be_a_name
?p1<-(person (name ?n1))
?p2<-(person (surname %%JUST_MATCH_n1%% ))
=>
(retract ?p2)
)
这有可能实现这样的目标吗?任何优化此规则的建议都将受到赞赏。
谢谢
P.S。抱歉这个荒谬的例子,但它很好地突出了我的情况。
如果要比较变量的相等性,在两个地方使用同一个变量比使用两个单独的变量并调用 = 或 eq 函数比较是否相等。在各种模式中,哈希表用于快速定位共享相同变量的事实,而当您使用函数调用来执行相等比较时则不会这样做。对于大量的事实,这可以提高几个数量级的性能:
CLIPS (6.31 6/12/19)
CLIPS> (clear)
CLIPS>
(deftemplate person
(slot name (type INTEGER))
(slot surname (type INTEGER)))
CLIPS>
(defrule surname_cant_be_a_name
?p1<- (person (name ?n1))
?p2<- (person (surname ?n2&:(= ?n1 ?n2)))
=>
(retract ?p2))
CLIPS> (timer (loop-for-count (?i 10000) (assert (person (name ?i) (surname (+ ?i 1))))))
12.3485549999987
CLIPS> (clear)
CLIPS>
(deftemplate person
(slot name (type INTEGER))
(slot surname (type INTEGER)))
CLIPS>
(defrule surname_cant_be_a_name
?p1 <- (person (name ?n1))
?p2 <- (person (surname ?n1))
=>
(retract ?p2))
CLIPS> (timer (loop-for-count (?i 10000) (assert (person (name ?i) (surname (+ ?i 1))))))
0.0177029999995284
CLIPS> (/ 12.3485549999987 0.0177029999995284)
697.540247434201
CLIPS>