【问题标题】:Generalization of set of facts in CLIPS (trying to find matching slot values in multislot slots)CLIPS 中事实集的泛化(尝试在多槽槽中找到匹配的槽值)
【发布时间】:2014-07-01 09:36:26
【问题描述】:

我正在尝试在 CLIPS 中做类似“事实概括”的事情(不确定哪个术语最能描述它),但我不确定如何以最好的方式做到这一点。

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

(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))))

问题在于,如果我们回到前面提到的这 4 个事实,它会断言:

(finalcause (coraxinfo 2) (changeinfo a))
(finalcause (coraxinfo 3) (changeinfo a))
(finalcause (coraxinfo 2 3) (changeinfo b))

等等

我不需要所有这些“部分匹配”,我只需要完全匹配的部分 - (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))

此时 CLIPS 引擎像无限循环一样进入 smth,LHS 列出所有可能的匹配项:

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

等等

这需要很长时间(并且仍然可以做我不需要的事情,正如我之前提到的)。我是 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)))

我需要将其作为输出:

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

【问题讨论】:

    标签: expert-system clips inference-engine generalization


    【解决方案1】:

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

    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> 
    

    这两种方法的关键部分是 forall 条件元素,它检查每个单因是否包含正在考虑的子序列。

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

    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> 
    

    【讨论】:

    • 嗨,哈利。谢谢你的回答。抱歉,看来我还没有澄清原始问题中的所有要点,让您感到困惑。我已经更新了它(请参阅原始问题的结尾)。长话短说,我需要在所有事实中找到所有可能的匹配项,我不希望在列表中的所有事实中找到相同的内容
    • 谢谢,哈利,看来是这样了。只是一个问题。我是否正确,如果我不知道 multislot 中应该匹配多少个后续插槽(目前在您提供的规则中,您假设其中有 2 个,但可能会有 4 个或 5 个或只有 1 个)我可以使用$?match11, $?match12 而不是 ?v11 ?v12 和 ?v21 ?v22 ?或者我需要为每个具有不同数量匹配字段的案例编写单独的规则?
    • 好的,看起来它可以工作了,现在唯一的问题是清理它造成的所有混乱。不知道如何做到最好,试试这个: (defrule cause_generalization_better ?f1 (retract ?f1))
    【解决方案2】:

    好的,在 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)
    

    【讨论】:

      猜你喜欢
      • 2014-07-07
      • 2014-07-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-01-17
      • 1970-01-01
      相关资源
      最近更新 更多