Expert system 片段中事实集的泛化(尝试在多段插槽中查找匹配的插槽值)

Expert system 片段中事实集的泛化(尝试在多段插槽中查找匹配的插槽值),expert-system,clips,inference-engine,generalization,Expert System,Clips,Inference Engine,Generalization,我试图在剪辑中做一些类似“事实概括”的事情(不确定哪个术语最能描述它),我不确定如何以最佳方式做到这一点 考虑这种情况。我有以下模板描述的一组事实: (deftemplate MAIN::simplecause (slot coraxidcause (type INTEGER) (default 0)) (slot changeidcause (type SYMBOL) (default PF1)) (multislot coraxinfo (type SYMBOL) (def

我试图在剪辑中做一些类似“事实概括”的事情(不确定哪个术语最能描述它),我不确定如何以最佳方式做到这一点

考虑这种情况。我有以下模板描述的一组事实:

(deftemplate MAIN::simplecause
   (slot coraxidcause (type INTEGER) (default 0))
   (slot changeidcause (type SYMBOL) (default PF1))
   (multislot coraxinfo (type SYMBOL) (default undefined))
   (multislot changeinfo (type SYMBOL) (default undefined)))  

(deftemplate MAIN::finalcause  
   (multislot coraxinfo (type SYMBOL) (default undefined))
   (multislot changeinfo (type SYMBOL) (default undefined))
   (slot casecount (type INTEGER) (default 0)))
Coraxidcause和changeidcause组合是一种键组合,这两个字段的组合是唯一的。changeinfo和coraxinfo在插槽中有一些符号值(每个插槽中的值始终不超过10个)

所以我有一些简单的事实。我想做的是找到changeinfo和coraxinfo中的哪些值相同,并断言它们。例如,如果我有这些简单的事实:

(simplecause (coraxidcause id1) (changeidcause id1) (coraxinfo 1 2 3) (changeinfo a b c))

(simplecause (coraxidcause id2) (changeidcause id2) (coraxinfo 2 3 6 7) (changeinfo e a b d f))

(simplecause (coraxidcause id3) (changeidcause id3) (coraxinfo 9 11 2 3 0) (changeinfo g a b))

(simplecause (coraxidcause id4) (changeidcause id4) (coraxinfo 77) (changeinfo z))
我想断言这样一个事实:

(finalcause (coraxinfo 2 3) (changeinfo a b))
现在我已经写了这条规则:

(defrule MAIN::cause_generalization_initial
   (simplecause (coraxidcause ?coraxid1) (changeidcause ?factid1) (coraxinfo $? $?coraxdetails $?) (changeinfo $? $?changedetails $?))
   (simplecause (coraxidcause ?coraxid2) (changeidcause ?factid2) (coraxinfo $? $?coraxdetails $?) (changeinfo $? $?changedetails $?))
   (or (test (<> ?coraxid1 ?coraxid2))
                                (neq ?factid1 ?factid2))
                (not (finalcause (coraxinfo $?coraxdetails) (changeinfo $?changeddetails)))
   =>
   (assert (finalcause (coraxinfo ?coraxdetails) (changeinfo ?changedetails) (casecount 0))))
等等

我不需要所有这些“部分匹配”,我只需要完全匹配的部分-(finalcause(coraxinfo 2 3)(changeinfo a b)),我不知道如何实现这一点。此外,当我有这样的事情时,会发生非常可怕的事情:

(simplecause (coraxidcause id5) (changeidcause id5) (coraxinfo 0 1 2 3) (changeidcause a b c))

(simplecause (coraxidcause id6) (changeidcause id6) (coraxinfo 6 1 2 3) (changeidcause a b c))
此时,剪辑引擎像一个无限循环一样进入smth,LHS列出了所有可能的匹配项:

(finalcause (coraxinfo 1) (changeidcause a))
(finalcause (coraxinfo 1) (changeidcause a b))
等等

这需要很长时间(而且仍然会做我之前提到的不需要的事情)。我是一个剪辑新手,所以我认为我错过了一些明显的东西,应该有一些方法来做我需要的。我将感谢任何帮助或建议如何做到这一点。任何想法都会非常有用

看来我还没弄清楚我到底想要什么。我需要找到所有事实的所有可能的“匹配项”,例如,如果我有这些事实:

    (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) (changeinfo abc def)))
我需要将其作为输出:

(finalcause (coraxinfo 2 3) (changeinfo a b))
(finalcause 88 99) (changeinfo k m)) 

你可以用一条规则来做到这一点,但它有点粗糙:

CLIPS> 
(deftemplate simplecause
   (multislot coraxinfo)
   (multislot changeinfo))
CLIPS>    
(deftemplate finalcause   
   (multislot coraxinfo)
   (multislot changeinfo))
CLIPS> 
(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)))
CLIPS> 
(defrule cause_generalization_initial
   ;; There's a simplecause with two subsequences
   (simplecause (coraxinfo $? $?coraxdetails $?) (changeinfo $? $?changedetails $?))
   ;; And every simplecause contains that same subsequence
   (forall (simplecause (coraxinfo $?all1) (changeinfo $?all2))
           (test (and (subsetp $?coraxdetails $?all1) (subsetp $?changedetails $?all2))))
   ;; And there's not a longer subsequence where every simplecause contains that subsequence
   (not (and (simplecause (coraxinfo $? $?coraxdetails2 $?) (changeinfo $? $?changedetails2 $?)) 
             (test (or (and (>= (length $?coraxdetails2) (length $?coraxdetails))
                            (> (length $?changedetails2) (length $?changedetails)))
                       (and (> (length $?coraxdetails2) (length $?coraxdetails))
                            (>= (length $?changedetails2) (length $?changedetails)))))
             (forall (simplecause (coraxinfo $?all1) (changeinfo $?all2))
                     (test (and (subsetp $?coraxdetails2 $?all1) (subsetp $?changedetails2 $?all2))))))
   ;; And a fact for the subsequences has not been generated (since 
   ;; the rule will have an activation for each simple cause)
   (not (finalcause (coraxinfo $?coraxdetails) (changeinfo $?changedetails)))
   =>
   (assert (finalcause (coraxinfo $?coraxdetails) (changeinfo $?changedetails))))
CLIPS> (reset)
CLIPS> (agenda)
0      cause_generalization_initial: f-3,*,*,*
0      cause_generalization_initial: f-2,*,*,*
0      cause_generalization_initial: f-1,*,*,*
For a total of 3 activations.
CLIPS> (watch rules)
CLIPS> (run)
FIRE    1 cause_generalization_initial: f-3,*,*,*
CLIPS> (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     (finalcause (coraxinfo 2 3) (changeinfo a b))
For a total of 5 facts.
CLIPS>
如果工作分散在多个规则之间,则更容易理解:

CLIPS> (unwatch all)
CLIPS> 
(deftemplate simplecause
   (multislot coraxinfo)
   (multislot changeinfo))
CLIPS>    
(deftemplate finalcause   
   (multislot coraxinfo)
   (multislot changeinfo))
CLIPS> 
(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)))
CLIPS> 
(defrule cause_generalization_initial
   (simplecause (coraxinfo $? $?coraxdetails $?) (changeinfo $? $?changedetails $?))
   (forall (simplecause (coraxinfo $?all1) (changeinfo $?all2))
           (test (and (subsetp $?coraxdetails $?all1) (subsetp $?changedetails $?all2))))
   =>
   (assert (finalcause (coraxinfo $?coraxdetails) (changeinfo $?changedetails))))
CLIPS> 
(defrule cause_generalization_better
   ?f <- (finalcause (coraxinfo $?coraxdetails1) (changeinfo $?changedetails1))
   (finalcause (coraxinfo $?coraxdetails2) (changeinfo $?changedetails2))
   (test (or (< (length $?coraxdetails1) (length $?coraxdetails2))
             (< (length $?changedetails1) (length $?changedetails2))))
   =>
   (retract ?f))
CLIPS> (reset)
CLIPS> (run)
CLIPS> (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-24    (finalcause (coraxinfo 2 3) (changeinfo a b))
For a total of 5 facts.
CLIPS> 
CLIPS>(全部取消匹配)
剪辑>
(大便
(多批次coraxinfo)
(多批次变更信息)
剪辑>
(金融用途)
(多批次coraxinfo)
(多批次变更信息)
剪辑>
(事实开始)
(简单原因(coraxinfo 1 2 3)(变更信息a b c))
(简单原因(coraxinfo 7 8 2 3 9)(更改信息d a b e))
(简单原因(coraxinfo 2 3 10 13)(更改信息f g a b z)))
剪辑>
(定义规则原因\u概括\u首字母)
(简单原因(coraxinfo$?$?coraxdetails$?)(changeinfo$?$?changedetails$?)
(对于所有(简单原因(coraxinfo$?ALL 1)(changeinfo$?ALL 2))
(测试(和(子测试$?coraxdetails$?all1)(子测试$?changedetails$?all2)))
=>
(断言(最终用途(coraxinfo$?coraxdetails)(changeinfo$?changedetails)))
剪辑>
(定义规则导致\u泛化\u更好
F
(收回?f))
剪辑>(重置)
剪辑>(运行)
剪辑>(事实)
f-0(初始事实)
f-1(简单原因(coraxinfo 1 2 3)(变更信息a b c))
f-2(简单原因(coraxinfo 7 8 2 3 9)(变更信息d a b e))
f-3(简单原因(coraxinfo 2 3 10 13)(更改信息f g a b z))
f-24(最终用途(Coraxinfo2-3)(变更信息a-b))
总共5个事实。
剪辑>
这两种方法的关键部分是forall条件元素,它检查每个simplecase是否包含所考虑的子序列

根据您的评论修改的方法:

CLIPS> (clear)
CLIPS>     
(deftemplate simplecause
   (multislot coraxinfo)
   (multislot changeinfo))
CLIPS>     
(deftemplate finalcause   
   (multislot coraxinfo)
   (multislot changeinfo))
CLIPS>  
(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) (changeinfo abc def)))
CLIPS>    
(defrule cause_generalization_initial
   ?f1 <- (simplecause (coraxinfo $? ?v11 ?v12 $?) (changeinfo $? ?v21 ?v22 $?))
   ?f2 <- (simplecause (coraxinfo $? ?v11 ?v12 $?) (changeinfo $? ?v21 ?v22 $?))
   (test (neq ?f1 ?f2))
   (not (finalcause (coraxinfo ?v11 ?v12) (changeinfo ?v21 ?v22)))
   =>
   (assert (finalcause (coraxinfo ?v11 ?v12) (changeinfo ?v21 ?v22))))
CLIPS> (reset)
CLIPS> (watch rules)
CLIPS> (run)
FIRE    1 cause_generalization_initial: f-6,f-5,*
FIRE    2 cause_generalization_initial: f-3,f-2,*
CLIPS> (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) (changeinfo abc def))
f-8     (finalcause (coraxinfo 88 99) (changeinfo k m))
f-9     (finalcause (coraxinfo 2 3) (changeinfo a b))
For a total of 10 facts.
CLIPS> 
剪辑>(清除)
剪辑>
(大便
(多批次coraxinfo)
(多批次变更信息)
剪辑>
(金融用途)
(多批次coraxinfo)
(多批次变更信息)
剪辑>
(事实开始)
(简单原因(coraxinfo 1 2 3)(变更信息a b c))
(简单原因(coraxinfo 7 8 2 3 9)(更改信息d a b e))
(简单原因(coraxinfo 2 3 10 13)(更改信息f g a b z))
(简单原因(coraxinfo 77 88 99 66)(变更信息k m l s))
(简单原因(coraxinfo 88 99 11 22)(变更信息v k m w))
(简单原因(coraxinfo 13 88 99)(变更信息k m))
(简单原因(coraxinfo 666 777)(changeinfo abc def)))
剪辑>
(定义规则原因\u概括\u首字母)
?f1(复位)
剪辑>(观看规则)
剪辑>(运行)
火灾原因1首字母:f-6,f-5*
火灾原因2首字母:f-3,f-2*
剪辑>(事实)
f-0(初始事实)
f-1(简单原因(coraxinfo 1 2 3)(变更信息a b c))
f-2(简单原因(coraxinfo 7 8 2 3 9)(变更信息d a b e))
f-3(简单原因(coraxinfo 2 3 10 13)(更改信息f g a b z))
f-4(简单原因(coraxinfo 77 88 99 66)(变更信息k m l s))
f-5(简单原因(coraxinfo 88 99 11 22)(变更信息v k m w))
f-6(简单原因(coraxinfo 138899)(变更信息k m))
f-7(简单原因(coraxinfo 666 777)(变更信息abc def))
f-8(最终用途(coraxinfo 88 99)(变更信息k m))
f-9(最终用途(Coraxinfo2-3)(变更信息a-b))
总共有10个事实。
剪辑>

好的,在Gary的帮助下,这里是最终结果:

(deftemplate simplecause
   (multislot coraxinfo)
   (multislot changeinfo))

(deftemplate finalcause   
   (multislot coraxinfo)
   (multislot changeinfo))

(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) (changeinfo abc def)))

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

(reset)

(run)

;retract simplecause facts and prevent them from adding 'partial matched final causes'
(do-for-all-facts ((?f simplecause)) TRUE (retract ?f)) 

;retracts partially matched facts so that we have only best matches
(defrule cause_generalization_better
   ?f1 <- (finalcause (coraxinfo $?match1) (changeinfo $?match2))
   ?f2 <- (finalcause (coraxinfo $?matchbig1) (changeinfo $?matchbig2))
   (test (and (subsetp $?match1 $?matchbig1) (subsetp $?match2 $?matchbig2) (neq ?f1 ?f2)))
   =>
   (retract ?f1))


;in some cases we can see facts like (finalcause (coraxinfo 13) (changeinfo))
;this happens when there is match by coraxinfo but no match by changeinfo or vice versa
;we retract such facts too

(defrule cause_generalization_remove_empty_coraxinfo
   ?f1 <- (finalcause (coraxinfo))
   =>
   (retract ?f1))

(defrule cause_generalization_remove_empty_changeinfo
   ?f1 <- (finalcause (changeinfo))
   =>
   (retract ?f1))

(run)
(大便)
(多批次coraxinfo)
(多批次变更信息)
(金融用途)
(多批次coraxinfo)
(多批次变更信息)
(事实开始)
(简单原因(coraxinfo 1 2 3)(变更信息a b c))
(简单原因(coraxinfo 7 8 2 3 9)(更改信息d a b e))
(简单原因(coraxinfo 2 3 10 13)(更改信息f g a b z))
(简单原因(coraxinfo 77 88 99 66)(变更信息k m l s))
(简单原因(coraxinfo 88 99 11 22)(变更信息v k m w))
(简单原因(coraxinfo 13 88 99)(变更信息k m))
(简单原因(coraxinfo 666 777)(changeinfo abc def)))
(定义规则原因\u概括\u首字母)

?f1嗨,哈利。谢谢你的回答。对不起,看起来我没有澄清原始问题中的所有要点,让你感到困惑。我已经更新了它(请参见原始问题的结尾).长话短说,我需要在所有事实中找到所有可能的匹配项,我不希望在列表中找到所有事实的相同项谢谢,哈利,看起来就是这样。再问一个问题。如果我不知道多批次中的后续插槽应匹配多少个,我是对的吗(目前在您提供的规则中,您假设有两个,但是
(deftemplate simplecause
   (multislot coraxinfo)
   (multislot changeinfo))

(deftemplate finalcause   
   (multislot coraxinfo)
   (multislot changeinfo))

(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) (changeinfo abc def)))

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

(reset)

(run)

;retract simplecause facts and prevent them from adding 'partial matched final causes'
(do-for-all-facts ((?f simplecause)) TRUE (retract ?f)) 

;retracts partially matched facts so that we have only best matches
(defrule cause_generalization_better
   ?f1 <- (finalcause (coraxinfo $?match1) (changeinfo $?match2))
   ?f2 <- (finalcause (coraxinfo $?matchbig1) (changeinfo $?matchbig2))
   (test (and (subsetp $?match1 $?matchbig1) (subsetp $?match2 $?matchbig2) (neq ?f1 ?f2)))
   =>
   (retract ?f1))


;in some cases we can see facts like (finalcause (coraxinfo 13) (changeinfo))
;this happens when there is match by coraxinfo but no match by changeinfo or vice versa
;we retract such facts too

(defrule cause_generalization_remove_empty_coraxinfo
   ?f1 <- (finalcause (coraxinfo))
   =>
   (retract ?f1))

(defrule cause_generalization_remove_empty_changeinfo
   ?f1 <- (finalcause (changeinfo))
   =>
   (retract ?f1))

(run)