我试图在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))
答案 0 :(得分: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条件元素,它检查每个simplecause是否包含正在考虑的子序列。
基于您的评论的修改方法:
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>
答案 1 :(得分:0)
好的,加里的帮助是最终结果:
(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)