CLIPS -查找多插槽字段中随机插槽之间的匹配



考虑这种情况。我有这样的模板:

(deftemplate MAIN::simplecause
   (multislot coraxinfo (type INTEGER) (default undefined))
   (multislot changeinfo (type SYMBOL) (default undefined)))
(deftemplate MAIN::finalcause   
   (multislot coraxinfo (type INTEGER) (default undefined))
   (multislot changeinfo (type SYMBOL) (default undefined)))

我知道在coraxinfo槽中,我将始终不超过14个值(可能更少,但永远不会更多)。我也现在在changeinfo multislot中,我将有不超过13个值。

我正在试着写一个规则,它将找到我所拥有的任何事实之间所有可能的匹配。

例如:

(deffacts start
       (simplecause (coraxinfo 1 2 3) (changeinfo a b c))
       (simplecause (coraxinfo 7 8 2 3 9) (changeinfo d a b e))
       (simplecause (coraxinfo 2 3 10 13) (changeinfo f g a b z))
       (simplecause (coraxinfo 77 88 99 66) (changeinfo k m l s))
       (simplecause (coraxinfo 88 99 11 22) (changeinfo v k m w))
       (simplecause (coraxinfo 13 88 99) (changeinfo k m))
       (simplecause (coraxinfo 666 777 888) (changeinfo abc def))
       (simplecause (coraxinfo 666 111 222 888 333 444 555 777 999) (changeinfo abc 1a 2a 3a def 4a)))

我需要得到这个(每个multislot中的值的顺序无关紧要):

(finalcause (coraxinfo 2 3) (changeinfo a b))
(finalcause 88 99) (changeinfo k m)) 
(finalcause 666 777 888) (changeinfo abc def)) 

现在我已经停止了这个函数:

(defrule cause_generalization_initial1
   ?f1 <- (simplecause (coraxinfo $?coraxmatch1 $?coraxmatch2 $?coraxmatch3 $?coraxmatch4 $?coraxmatch5 $?coraxmatch6 $?coraxmatch7) (changeinfo $?pricematch1 $?pricematch2 $?pricematch3 $?pricematch4 $?pricematch5 $?pricematch6 $?pricematch7))
   ?f2 <- (simplecause (coraxinfo $?coraxmatch1 $?coraxmatch2 $?coraxmatch3 $?coraxmatch4 $?coraxmatch5 $?coraxmatch6 $?coraxmatch7) (changeinfo $?pricematch1 $?pricematch2 $?pricematch3 $?pricematch4 $?pricematch5 $?pricematch6 $?pricematch7))
   (test (neq ?f1 ?f2))
   (not (finalcause (coraxinfo $?coraxmatch1 $?coraxmatch2 $?coraxmatch3 $?coraxmatch4 $?coraxmatch5 $?coraxmatch6 $?coraxmatch7) (changeinfo $?pricematch1 $?pricematch2 $?pricematch3 $?pricematch4 $?pricematch5 $?pricematch6 $?pricematch7)))
   =>
   (assert (finalcause (coraxinfo $?coraxmatch1 $?coraxmatch2 $?coraxmatch3 $?coraxmatch4 $?coraxmatch5 $?coraxmatch6 $?coraxmatch7) (changeinfo $?pricematch1 $?pricematch2 $?pricematch3 $?pricematch4 $?pricematch5 $?pricematch6 $?pricematch7))))

这是有点笨拙,但就我所记得的$?意味着"零或更多",所以即使我将有比我在搜索模式中指定的更少的字段,它应该工作。我在每个模式中最多使用7个multislot,因为拥有14或13个值作为最大值意味着在最坏的情况下,multislot中的每秒钟值都将匹配到其他情况下的smth。

当我加载在defaultclips中指定的事实时,会进入一种无限循环-它长时间没有响应,所以我相信我在规则中犯了一个错误。此外,这条规则应该杀死引擎的情况下,我将有一对夫妇的事实,这是几乎相同的差异,只有在一个领域。在这种情况下,它们之间会产生大量的匹配。知道我哪里错了吗?我将非常感谢任何建议。

更新。如果我们试图通过在coraxinfo和changeinfo插槽中添加一个值来构建(最终原因)事实的方法,那么我目前已经停止了这2条规则:

在两个multislot中使用一个匹配的值创建初始的finalcause fact:

(defrule cause_generalization_initial
    ?f1 <- (simplecause (coraxinfo $? ?coraxmatch $?) (changeinfo $? ?changematch $?))
    ?f2 <- (simplecause (coraxinfo $? ?coraxmatch $?) (changeinfo $? ?changematch $?))
    (test (neq ?f1 ?f2))
    (not (finalcause (coraxinfo ?coraxmatch) (changeinfo ?changematch)))
    =>
    (assert (finalcause (coraxinfo ?coraxmatch) (changeinfo ?changematch)))

如果我们有任何最终原因事实,我们尝试检查其中的所有多槽值都是匹配简单原因事实中的?coraxmatchafter值之前的所有值的子集,并断言扩展的最终原因。我相信这条规则应该能够在匹配简单原因时"跳过空白"。

(defrule cause_generalization_advanced
?f1 <- (simplecause (coraxinfo $?coraxbefore1 ?coraxmatchafter $?) (changeinfo $?changebefore1 ?changematchafter $?))
?f2 <- (simplecause (coraxinfo $?coraxbefore2 ?coraxmatchafter $?) (changeinfo $?changebefore2 ?changematchafter $?))
(test (neq ?f1 ?f2))
(finalcause (coraxinfo $?finalcoraxbefore) (changeinfo $?finalchangebefore))
(test (and  (subsetp $?finalcoraxbefore $?coraxbefore1) (subsetp $?finalcoraxbefore $?coraxbefore2) 
        (subsetp $?finalchangebefore $?changebefore1) (subsetp $?finalchangebefore $?changebefore2)))
=>
(assert (finalcause (coraxinfo $?finalcoraxbefore ?coraxmatchafter) (changeinfo $?finalchangebefore ?changematchafter))))

我使用带有这些差异的规则(请注意,差异与上面的不同):

(deffacts start
       (simplecause (coraxinfo 1 2 3) (changeinfo a b c))
       (simplecause (coraxinfo 7 8 2 3 9) (changeinfo d a b e))
       (simplecause (coraxinfo 2 3 10 13) (changeinfo f g a b z))
       (simplecause (coraxinfo 77 88 99 66) (changeinfo k m l s))
       (simplecause (coraxinfo 88 99 11 22) (changeinfo v k m w))
       (simplecause (coraxinfo 13 88 99) (changeinfo k m))
       (simplecause (coraxinfo 666 777 888) (changeinfo abc def))
       (simplecause (coraxinfo 666 111 222 777 333 444 555 888 999) (changeinfo abc 1a 2a 3a def 4a)))

这里的问题是,我预计它将能够产生3个匹配字段的最终原因,但它只产生具有2个匹配字段的最终原因事实,我不明白为什么。难道它没有注意到这3个事实属于第二条规则吗?

(simplecause (coraxinfo 666 777 888) (changeinfo abc def))
(simplecause (coraxinfo 666 111 222 777 333 444 555 888 999) (changeinfo abc 1a 2a 3a def 4a))
(finalcause (coraxinfo 666 888) (changeinfo abc def))
Output of both rules is:
f-0     (initial-fact)
f-1     (simplecause (coraxinfo 1 2 3) (changeinfo a b c))
f-2     (simplecause (coraxinfo 7 8 2 3 9) (changeinfo d a b e))
f-3     (simplecause (coraxinfo 2 3 10 13) (changeinfo f g a b z))
f-4     (simplecause (coraxinfo 77 88 99 66) (changeinfo k m l s))
f-5     (simplecause (coraxinfo 88 99 11 22) (changeinfo v k m w))
f-6     (simplecause (coraxinfo 13 88 99) (changeinfo k m))
f-7     (simplecause (coraxinfo 666 777 888) (changeinfo abc def))
f-8     (simplecause (coraxinfo 666 111 222 777 333 444 555 888 999) (changeinfo abc 1a 2a 3a def 4a))
f-9     (finalcause (coraxinfo 666) (changeinfo abc))
f-10    (finalcause (coraxinfo 666 888) (changeinfo abc def))
f-11    (finalcause (coraxinfo 666 777) (changeinfo abc def))
f-12    (finalcause (coraxinfo 666) (changeinfo def))
f-13    (finalcause (coraxinfo 777) (changeinfo abc))
f-14    (finalcause (coraxinfo 777 888) (changeinfo abc def))
f-15    (finalcause (coraxinfo 777) (changeinfo def))
f-16    (finalcause (coraxinfo 888) (changeinfo abc))
f-17    (finalcause (coraxinfo 888) (changeinfo def))
f-18    (finalcause (coraxinfo 88) (changeinfo k))
f-19    (finalcause (coraxinfo 88 99) (changeinfo k m))
f-20    (finalcause (coraxinfo 88) (changeinfo m))
f-21    (finalcause (coraxinfo 99) (changeinfo k))
f-22    (finalcause (coraxinfo 99) (changeinfo m))
f-23    (finalcause (coraxinfo 2) (changeinfo a))
f-24    (finalcause (coraxinfo 2 3) (changeinfo a b))
f-25    (finalcause (coraxinfo 2) (changeinfo b))
f-26    (finalcause (coraxinfo 3) (changeinfo a))
f-27    (finalcause (coraxinfo 3) (changeinfo b))

使用7个多字段变量,您正在创建模式匹配方式的组合爆炸。查看规则中的第一个模式可以匹配的方法的数量:

CLIPS> 
(deftemplate simplecause
   (multislot coraxinfo)
   (multislot changeinfo))
CLIPS> 
(deftemplate  finalcause   
   (multislot coraxinfo)
   (multislot changeinfo))
CLIPS>    
(defrule cause_generalization_initial1
   (simplecause (coraxinfo $?coraxmatch1 $?coraxmatch2 $?coraxmatch3 $?coraxmatch4 $?coraxmatch5 $?coraxmatch6 $?coraxmatch7) 
                (changeinfo $?pricematch1 $?pricematch2 $?pricematch3 $?pricematch4 $?pricematch5 $?pricematch6 $?pricematch7))
   =>)
CLIPS> (assert (simplecause (coraxinfo) (changeinfo)))
<Fact-1>
CLIPS> (agenda)
0      cause_generalization_initial1: f-1
For a total of 1 activation.
CLIPS> (modify 1 (coraxinfo a) (changeinfo 1))
<Fact-2>
CLIPS> (agenda)
0      cause_generalization_initial1: f-2
   .
   .
   .
0      cause_generalization_initial1: f-2
For a total of 49 activations.
CLIPS> (modify 2 (coraxinfo a b) (changeinfo 1 2))
<Fact-3>
CLIPS> (agenda)
0      cause_generalization_initial1: f-3
   .
   .
   .
0      cause_generalization_initial1: f-3
For a total of 784 activations.
CLIPS> (modify 3 (coraxinfo a b c) (changeinfo 1 2 3))
<Fact-4>
CLIPS> (agenda)
0      cause_generalization_initial1: f-4
   .
   .
   .
0      cause_generalization_initial1: f-4
For a total of 7056 activations.

CLIPS> (modify 4 (coraxinfo a b c d) (changeinfo 1 2 3 4))
<Fact-5>
CLIPS> (agenda)
0      cause_generalization_initial1: f-5
   .
   .
   .
0      cause_generalization_initial1: f-5
For a total of 44100 activations.
CLIPS>

如果coraxinfo和changeinfo槽是空的,那么只有一种方法可以匹配模式并且只有一次激活。如果每个槽包含一个值,那么每个槽有7种不同的匹配方式(7个变量中的每个变量都有一个值,其余变量为空)。在这两个槽之间意味着有49种不同的模式可以匹配。

一旦你在每个槽中得到4个值,就有44100种不同的方式可以匹配单个模式。这意味着通过添加第二个模式,有44100 * 44100个组合需要进行比较。对于单个事实的断言,需要进行1,944,810,000次比较,并且您有8个事实,其中一个事实在一个槽中有9个值,另一个槽中有6个值。

这不是一个你用一条规则就能解决的问题。也许最好的方法是使用多个规则一次构建一个元素的最终原因事实。例如,首先确定有两个包含666的事实,并创建一个(finalcause (coraxinfo 666) (changeinfo))事实。然后有一个规则,确定有两个事实,它们都具有finalcause中所有的值,加上一个不存在的附加值,并将该值相加。例如:(finalcause (coraxinfo 666 777) (changeinfo))。然后,您可以设置删除中间结果的规则。

您还需要构建规则,这样您就不会生成排列。例如,您不希望生成所有不同但等效的事实:

(finalcause (coraxinfo 666 777 888) (changeinfo abc def))
(finalcause (coraxinfo 666 888 777) (changeinfo abc def))
(finalcause (coraxinfo 777 666 888) (changeinfo abc def))
(finalcause (coraxinfo 777 888 666) (changeinfo abc def))
(finalcause (coraxinfo 888 666 777) (changeinfo abc def))
(finalcause (coraxinfo 888 777 666) (changeinfo abc def))
(finalcause (coraxinfo 666 777 888) (changeinfo def abc))
(finalcause (coraxinfo 666 888 777) (changeinfo def abc))
(finalcause (coraxinfo 777 666 888) (changeinfo def abc))
(finalcause (coraxinfo 777 888 666) (changeinfo def abc))
(finalcause (coraxinfo 888 666 777) (changeinfo def abc))
(finalcause (coraxinfo 888 777 666) (changeinfo def abc))

要做到这一点,我建议对您放置在finalcause槽中的值进行排序,以便等效事实有唯一的顺序。

在Gary的帮助下,下面是实现这一功能的变体:

(deftemplate MAIN::simplecause
   (multislot coraxinfo (type INTEGER) (default 0))
   (multislot changeinfo (type SYMBOL) (default undefined)))
(deftemplate MAIN::finalcause   
   (multislot coraxinfo (type INTEGER) (default 0))
   (multislot changeinfo (type SYMBOL) (default undefined)))
(deffacts start
       (simplecause (coraxinfo 1 2 3) (changeinfo a b c))
       (simplecause (coraxinfo 7 8 2 3 9) (changeinfo d a b e))
       (simplecause (coraxinfo 2 3 10 13) (changeinfo f g a b z))
       (simplecause (coraxinfo 77 88 99 66) (changeinfo k m l s))
       (simplecause (coraxinfo 88 99 11 22) (changeinfo v k m w))
       (simplecause (coraxinfo 13 88 99) (changeinfo k m))
       (simplecause (coraxinfo 666 777 888) (changeinfo abc def))
       (simplecause (coraxinfo 666 111 222 777 333 444 555 888 999) (changeinfo abc 1a 2a 3a def 4a)))
(defrule cause_generalization_advanced_corax
    ?f1 <- (simplecause (coraxinfo $?coraxbefore1 ?coraxmatchafter $?) (changeinfo $?changebefore1))
    ?f2 <- (simplecause (coraxinfo $?coraxbefore2 ?coraxmatchafter $?) (changeinfo $?changebefore2))
    (test (neq ?f1 ?f2))
    (finalcause (coraxinfo $?finalcoraxbefore) (changeinfo $?finalchangebefore))
    (test (and  (subsetp $?finalcoraxbefore $?coraxbefore1) (subsetp $?finalcoraxbefore $?coraxbefore2) 
            (subsetp $?finalchangebefore $?changebefore1) (subsetp $?finalchangebefore $?changebefore2)))
    =>
    (assert (finalcause (coraxinfo $?finalcoraxbefore ?coraxmatchafter) (changeinfo $?finalchangebefore))))

(defrule cause_generalization_advanced_change
    ?f1 <- (simplecause (coraxinfo $?coraxbefore1) (changeinfo $?changebefore1 ?changematchafter $?))
    ?f2 <- (simplecause (coraxinfo $?coraxbefore2) (changeinfo $?changebefore2 ?changematchafter $?))
    (test (neq ?f1 ?f2))
    (finalcause (coraxinfo $?finalcoraxbefore) (changeinfo $?finalchangebefore))
    (test (and  (subsetp $?finalcoraxbefore $?coraxbefore1) (subsetp $?finalcoraxbefore $?coraxbefore2) 
            (subsetp $?finalchangebefore $?changebefore1) (subsetp $?finalchangebefore $?changebefore2)))
    =>
    (assert (finalcause (coraxinfo $?finalcoraxbefore) (changeinfo $?finalchangebefore ?changematchafter))))
(reset)
(run)
(facts)
f-0     (initial-fact)
f-1     (simplecause (coraxinfo 1 2 3) (changeinfo a b c))
f-2     (simplecause (coraxinfo 7 8 2 3 9) (changeinfo d a b e))
f-3     (simplecause (coraxinfo 2 3 10 13) (changeinfo f g a b z))
f-4     (simplecause (coraxinfo 77 88 99 66) (changeinfo k m l s))
f-5     (simplecause (coraxinfo 88 99 11 22) (changeinfo v k m w))
f-6     (simplecause (coraxinfo 13 88 99) (changeinfo k m))
f-7     (simplecause (coraxinfo 666 777 888) (changeinfo abc def))
f-8     (simplecause (coraxinfo 666 111 222 777 333 444 555 888 999) (changeinfo abc 1a 2a 3a def 4a))
f-9     (finalcause (coraxinfo 666) (changeinfo abc))
f-10    (finalcause (coraxinfo 666 888) (changeinfo abc))
f-11    (finalcause (coraxinfo 666 888) (changeinfo abc def))
f-12    (finalcause (coraxinfo 666 777) (changeinfo abc))
f-13    (finalcause (coraxinfo 666 777 888) (changeinfo abc))
f-14    (finalcause (coraxinfo 666 777 888) (changeinfo abc def))
f-15    (finalcause (coraxinfo 666 777) (changeinfo abc def))
f-16    (finalcause (coraxinfo 666) (changeinfo abc def))
f-17    (finalcause (coraxinfo 666) (changeinfo def))
f-18    (finalcause (coraxinfo 666 888) (changeinfo def))
f-19    (finalcause (coraxinfo 666 777) (changeinfo def))
f-20    (finalcause (coraxinfo 666 777 888) (changeinfo def))
f-21    (finalcause (coraxinfo 777) (changeinfo abc))
f-22    (finalcause (coraxinfo 777 888) (changeinfo abc))
f-23    (finalcause (coraxinfo 777 888) (changeinfo abc def))
f-24    (finalcause (coraxinfo 777) (changeinfo abc def))
f-25    (finalcause (coraxinfo 777) (changeinfo def))
f-26    (finalcause (coraxinfo 777 888) (changeinfo def))
f-27    (finalcause (coraxinfo 888) (changeinfo abc))
f-28    (finalcause (coraxinfo 888) (changeinfo abc def))
f-29    (finalcause (coraxinfo 888) (changeinfo def))
f-30    (finalcause (coraxinfo 88) (changeinfo k))
f-31    (finalcause (coraxinfo 88 99) (changeinfo k))
f-32    (finalcause (coraxinfo 88 99) (changeinfo k m))
f-33    (finalcause (coraxinfo 88) (changeinfo k m))
f-34    (finalcause (coraxinfo 88) (changeinfo m))
f-35    (finalcause (coraxinfo 88 99) (changeinfo m))
f-36    (finalcause (coraxinfo 99) (changeinfo k))
f-37    (finalcause (coraxinfo 99) (changeinfo k m))
f-38    (finalcause (coraxinfo 99) (changeinfo m))
f-39    (finalcause (coraxinfo 2) (changeinfo a))
f-40    (finalcause (coraxinfo 2 3) (changeinfo a))
f-41    (finalcause (coraxinfo 2 3) (changeinfo a b))
f-42    (finalcause (coraxinfo 2) (changeinfo a b))
f-43    (finalcause (coraxinfo 2) (changeinfo b))
f-44    (finalcause (coraxinfo 2 3) (changeinfo b))
f-45    (finalcause (coraxinfo 3) (changeinfo a))
f-46    (finalcause (coraxinfo 3) (changeinfo a b))
f-47    (finalcause (coraxinfo 3) (changeinfo b))

最新更新