2017-05-20 5 views
1

私は文字A、B、C、D、Eで5x5の行列を埋めなければならない問題を解決しようとしています。各行は各行と各列に複数回出現することはできません。いくつかの最初の文字位置が与えられています。 私はすべてのポジションを別々の事実として作成しました。 "M 1 1 X"。 私は正しい文字で事実を表明し、条件をもう一度確認するために喧嘩をループする方法を苦労しています。例えば上記CLIPSのルーピングディフルー

(defrule solveA5 
?a <-(M 5 ?c X) 
(not (M ?x ?c A)) 
=> 
(retract ?a) 
(assert (M 5 ?c A)) 
) 

コードは、5行目のどの位置にAの存在を確認することですが、問題は条件が始まったばかり、代わりに正しい事実を主張して、もう一度チェックのそれは中をアサートでチェックされていることですあらゆる位置。

deffunctionを使用してループを解消しようとしました。

(deffunction solve (?letter) 
(loop-for-count (?x 1 5) do 
    (loop-for-count (?y 1 5) do 
     (build (str-cat"defrule costam 
      ?a <-(M ?x ?y X) 
      (not (and(M ?x ?a ?letter) (M ?b ?y ?letter)) 
      => 
      (retract ?a) 
      (assert (M ?x ?y ?letter))") 
     ) 
    ) 
) 
) 

は、残念ながら "FALSE"

(solve A) 

リターンを実行し、すべての事実を変更しません。

答えて

0

ルール内の反復を処理するには、反復情報をファクトとしてアサートして、ルールがこの情報を照合して変更できるようにする必要があります。配置では、それが特定の順序でこれを行うために必要不可欠ではありませんので、あなただけの行、列、および任意のルールの火を置き、許可する文字を含む情報をアサートすることができます

CLIPS> 
(deftemplate element 
    (slot row) 
    (slot column) 
    (slot value)) 
CLIPS>  
(deftemplate print 
    (slot row) 
    (slot column) 
    (slot end-of-row)) 
CLIPS>  
(deffacts initial 
    (rows 1 2 3 4 5) 
    (columns 1 2 3 4 5) 
    (letters A B C D E)) 
CLIPS>  
(defrule place 
    (rows $? ?r1 $?) 
    (columns $? ?c1 $?) 
    (letters $? ?l $?) 
    (not (element (row ?r1) (column ?c1))) 
    (not (and (element (row ?r2) 
         (column ?c2) 
         (value ?l)) 
      (test (or (= ?r1 ?r2) (= ?c1 ?c2))))) 
    => 
    (assert (element (row ?r1) (column ?c1) (value ?l)))) 
CLIPS>   
(defrule print-start 
    (declare (salience -10)) 
    (rows ?r $?) 
    (columns ?c $?rest) 
    => 
    (assert (print (row ?r) 
        (column ?c) 
        (end-of-row (= (length$ ?rest) 0))))) 
CLIPS>  
(defrule print-next-column 
    (declare (salience -10)) 
    ?f <- (print (column ?c)) 
    (columns $? ?c ?nc $?rest) 
    => 
    (modify ?f (column ?nc) 
       (end-of-row (= (length$ ?rest) 0)))) 
CLIPS> 
(defrule print-next-row 
    (declare (salience -10)) 
    ?f <- (print (column ?c) (row ?r)) 
    (columns $?first ?c) 
    (rows $? ?r ?nr $?) 
    => 
    (if (= (length$ ?first) 0) 
     then 
     (bind ?eor TRUE) 
     (bind ?nc ?c) 
     else 
     (bind ?eor FALSE) 
     (bind ?nc (nth$ 1 ?first))) 
    (modify ?f (row ?nr) 
       (column ?nc) 
       (end-of-row ?eor))) 
CLIPS>  
(defrule print-placed 
    (print (row ?r) (column ?c) (end-of-row ?eor)) 
    (element (row ?r) (column ?c) (value ?l)) 
    => 
    (if ?eor 
     then 
     (printout t ?l crlf) 
     else 
     (printout t ?l " "))) 
CLIPS> 
(defrule print-unplaced 
    (print (row ?r) (column ?c) (end-of-row ?eor)) 
    (not (element (row ?r) (column ?c))) 
    => 
    (if ?eor 
     then 
     (printout t "?" crlf) 
     else 
     (printout t "? "))) 
CLIPS> (reset) 
CLIPS> (run) 
E D C B A 
? C D A B 
? B A D C 
? A B C D 
A ? ? ? E 
CLIPS> 

この例では、印刷ルールは、反復情報をファクトに格納することによって行と列を反復処理します。これは、要素を任意の方法で割り当てる場所規則よりもはるかに複雑であることがわかります。

値を任意にまたは特定の順序で割り当てるかどうかにかかわらず、解決策を防止する値を割り当てることができるため、解決策を見つけるためにバックトラックを実装する必要があります。この例では、事実が試みられてきた値のプレースメントと値の順序に関する情報を格納:

CLIPS> (clear) 
CLIPS> 
(deftemplate element 
    (slot row) 
    (slot column) 
    (slot value (default unset)) 
    (multislot values) 
    (slot placement)) 
CLIPS>  
(deffacts initial 
    (placement 0) 
    (rows 1 2 3 4 5) 
    (columns 1 2 3 4 5) 
    (letters A B C D E)) 
CLIPS>  
(defrule prime 
    (placement ?p) 
    (rows $? ?r $?) 
    (columns $? ?c $?) 
    (letters $?l) 
    (not (element (placement ?p))) 
    (not (element (row ?r) (column ?c))) 
    => 
    (assert (element (placement ?p) (values ?l) (row ?r) (column ?c)))) 
CLIPS>  
(defrule place-good 
    ?f1 <- (placement ?p) 
    ?f2 <- (element (placement ?p) 
        (value unset) 
        (row ?r1) 
        (column ?c1) 
        (values ?v $?rest)) 
    (not (and (element (row ?r2) 
         (column ?c2) 
         (value ?v)) 
      (test (or (= ?r1 ?r2) (= ?c1 ?c2))))) 
    => 
    (retract ?f1) 
    (assert (placement (+ ?p 1))) 
    (modify ?f2 (value ?v) (values ?rest))) 
CLIPS>  
(defrule place-bad 
    (placement ?p) 
    ?f2 <- (element (placement ?p) 
        (value unset) 
        (row ?r1) 
        (column ?c1) 
        (values ?v $?rest)) 
    (element (row ?r2) 
      (column ?c2) 
      (value ?v)) 
    (test (or (= ?r1 ?r2) (= ?c1 ?c2))) 
    => 
    (modify ?f2 (values ?rest))) 
CLIPS>  
(defrule backtrack 
    ?f1 <- (placement ?p) 
    ?f2 <- (element (placement ?p) 
        (value unset) 
        (values)) 
    ?f3 <- (element (placement =(- ?p 1)) 
        (value ~unset)) 
    => 
    (retract ?f1) 
    (assert (placement (- ?p 1))) 
    (retract ?f2) 
    (modify ?f3 (value unset))) 
CLIPS>  
(defrule print 
    (declare (salience -10)) 
    (rows $?rows) 
    (columns $?columns) 
    => 
    (progn$ (?r ?rows) 
     (progn$ (?c ?columns) 
     (if (not (do-for-fact ((?f element)) 
           (and (= ?r ?f:row) (= ?c ?f:column)) 
        (printout t ?f:value " "))) 
      then 
      (printout t "? "))) 
     (printout t crlf))) 
CLIPS> (reset) 
CLIPS> (run) 
B C D E A 
A B C D E 
C A E B D 
D E A C B 
E D B A C 
CLIPS> 

印刷ルールを単一のルールに簡略化されていることアクションの行および列を反復処理ファクト・クエリー関数を使用して割り当てられた値を検索します。

あなたが値の一部を事前に割り当てる場合、プログラムも動作します:

CLIPS> (reset) 
CLIPS> (assert (element (row 1) (column 1) (value A))) 
<Fact-5> 
CLIPS> (assert (element (row 3) (column 3) (value C))) 
<Fact-6> 
CLIPS> (assert (element (row 5) (column 4) (value E))) 
<Fact-7> 
CLIPS> (run) 
A C E D B 
B A D C E 
D E C B A 
E D B A C 
C B A E D 
CLIPS>