1

私はエキスパート システム、特に CLIPS の初心者です (英語以外にも :-) )。

複雑な比較述語を使用して、事実の中から(ある意味で)最大値を見つけようとしています。比較述語は、引数として 2 つの事実を取る関数として実装されます。簡単に言えば、すべての事実を実行し、述語を使用して比較を行い、最大の事実を 1 つ返すには CLIPS が必要です。

解決策の 1 つは、CLIPS ルールを使用して次の式を評価することです。

( Exists x) and not ((Exists y)(y != x) and (y>x))

ここで、">" は私の述語を表し、x と y は次のような事実です。

(deftemplate fact (slot name ... ) ... )
(deffunction my-predicate ""
(?fact1 ?fact2)
...
)
(defrule find-max ""
    ?fact1 <- (fact (name ?name1) )
    ( not (test (my-predicate ?fact1 (fact (name ?name2 )))))
=>
...
)

しかし、この例は my-predicate 関数呼び出しの 2 番目の引数に関するエラー メッセージのために機能しません。

もう 1 つの解決策は、特定の名前と述語の比較関数の値を持つ基本事実を表す中間事実を作成することです。ただし、最終的な結果を得るには、数回の反復が必要です。

私は最初の解決策を好みますが、それをコーディングする方法がわかりません。この質問への回答のようなものが必要だと思います。違いは、私の質問が 1 つのスロットだけでなく、事実全体の比較に関するものであることです。

ルールの 1 回のアクティブ化の最大値を見つけることは可能ですか? 可能であれば、その方法を説明してください。

4

1 に答える 1

8

単純な比較で通常行う方法は次のとおりです。

CLIPS> (clear)
CLIPS> 
(deftemplate fact (slot name) (slot value))
CLIPS> 
(deffacts test-data
   (fact (name data-1) (value 3))
   (fact (name data-2) (value 1))
   (fact (name data-3) (value 2))
   (fact (name data-4) (value 2))
   (fact (name data-5) (value 4))
   (fact (name data-6) (value 3)))
CLIPS> 
(defrule find-max-value
   (fact (name ?name1) (value ?value1))
   (not (fact (value ?value2&:(> ?value2 ?value1))))
   =>
   (printout t "Fact " ?name1 " is the maximum" crlf))
CLIPS> (reset)
CLIPS> (run)
Fact data-5 is the maximum
CLIPS> 

比較に必要なすべてのスロット値をバインドして関数に渡す場合も、同じ基本的なアプローチが機能します。

CLIPS> (clear)
CLIPS> 
(deftemplate fact (slot name) (slot value))
CLIPS> 
(deffacts test-data
   (fact (name data-1) (value 3))
   (fact (name data-2) (value 1))
   (fact (name data-3) (value 2))
   (fact (name data-4) (value 2))
   (fact (name data-5) (value 4))
   (fact (name data-6) (value 3)))
CLIPS> 
(deffunction my-predicate (?value1 ?value2)
   (> ?value1 ?value2))
CLIPS>    
(defrule find-max-value
   (fact (name ?name1) (value ?value1))
   (not (fact (value ?value2&:(my-predicate ?value2 ?value1))))
   =>
   (printout t "Fact " ?name1 " is the maximum" crlf))
CLIPS> (reset)
CLIPS> (run)
Fact data-5 is the maximum
CLIPS> 

ただし、ファクトを関数に渡すと問題が発生します。これは、パターンを条件なし要素内のファクト アドレスにバインドできないためです。ファクトに一意の識別子として機能するスロットがある場合、これを使用してファクトへのポインターを取得できます (ただし、この方法はお勧めしません)。

CLIPS> (clear)
CLIPS> 
(deftemplate fact (slot name) (slot value))
CLIPS> 
(deffacts test-data
   (fact (name data-1) (value 3))
   (fact (name data-2) (value 1))
   (fact (name data-3) (value 2))
   (fact (name data-4) (value 2))
   (fact (name data-5) (value 4))
   (fact (name data-6) (value 3)))
CLIPS> 
(deffunction my-predicate (?fact1 ?fact2)
   (> (fact-slot-value ?fact1 value) (fact-slot-value ?fact2 value)))
CLIPS> 
(defrule find-max-value
   ?fact1 <- (fact (name ?name1))
   (not (fact (name ?name2&:(my-predicate (nth$ 1 (find-fact ((?fact2 fact)) 
                                                               (eq ?fact2:name ?name2))) 
                                            ?fact1))))
   =>
   (printout t "Fact " ?name1 " is the maximum" crlf))
CLIPS> (reset)
CLIPS> (run)
Fact data-5 is the maximum
CLIPS> 

私がお勧めするのは、ファクト クエリ関数を使用してファクトを繰り返し処理し、最大値を見つけることです。

CLIPS> (clear)
CLIPS> 
(deftemplate fact (slot name) (slot value))
CLIPS> 
(deffacts test-data
   (fact (name data-1) (value 3))
   (fact (name data-2) (value 1))
   (fact (name data-3) (value 2))
   (fact (name data-4) (value 2))
   (fact (name data-5) (value 4))
   (fact (name data-6) (value 3)))
CLIPS> 
(deffunction my-predicate (?fact1 ?fact2)
   (> (fact-slot-value ?fact1 value) (fact-slot-value ?fact2 value)))
CLIPS> 
(deffunction find-max (?template ?predicate)
   (bind ?max FALSE)
   (do-for-all-facts ((?f ?template)) TRUE
      (if (or (not ?max) (funcall ?predicate ?f ?max))
         then
         (bind ?max ?f)))
   (return ?max))
CLIPS>    
(reset)
CLIPS> (facts)
f-0     (initial-fact)
f-1     (fact (name data-1) (value 3))
f-2     (fact (name data-2) (value 1))
f-3     (fact (name data-3) (value 2))
f-4     (fact (name data-4) (value 2))
f-5     (fact (name data-5) (value 4))
f-6     (fact (name data-6) (value 3))
For a total of 7 facts.
CLIPS> (find-max fact my-predicate)
<Fact-5>
CLIPS> 
(defrule find-max
   =>
   (bind ?fact (find-max fact my-predicate))
   (if ?fact
      then
      (printout t "Fact " (fact-slot-value ?fact name) " is the maximum" crlf)))
CLIPS> (run)
Fact data-5 is the maximum
CLIPS> 

CLIPS はサポートしていませんが、多くの言語は累積条件要素をサポートしており、このタイプの計算をより簡単に実行できます。たとえば、Jess では次のことができます。

Jess> 
(deftemplate fact (slot name) (slot value))
TRUE
Jess> 
(deffacts test-data
   (fact (name data-1) (value 3))
   (fact (name data-2) (value 1))
   (fact (name data-3) (value 2))
   (fact (name data-4) (value 2))
   (fact (name data-5) (value 4))
   (fact (name data-6) (value 3)))
TRUE
Jess> (if FALSE then 3 else 4)
4
Jess> 
(defrule find-max-value
   ?c <- (accumulate (bind ?max FALSE)
                     (if (or (not ?max) (> ?value ?max))
                         then (bind ?max ?value))
                     ?max
                     (fact (value ?value)))
   =>
   (printout t "The max is " ?c crlf))
TRUE
Jess> (reset)
TRUE
Jess> (run)
The max is 4
1
Jess> 
于 2013-11-29T22:07:31.307 に答える