0

ナレッジ ベースに次の事実があります。

line(a,b). -- denotes the line determined by point a and b
line(c,d). -- denotes the line determined by point c and d
lineEqual(line(a,b),line(c,d)) -- denotes the length of two lines are equal

lineEqual/2 の 2 つの引数を交換できる別のルールが必要です。

lineEqual(line(C, D), line(A, B)):-
    lineEqual(line(A,B),line(C,D)). 

残念ながら、ルールは Prolog で無限ループを作成します。他のアイデアはありますか?

更新していただきありがとうございます。最後のルールを理解できたかどうかわかりません:

transitiveSymmetricRelPath(L1, L2, IntermediateNodes) :- symmetricRel(L1, L3),
                 \+member(L3, IntermediateNodes),
                 transitiveSymmetricRelPath(L1, L2, [L3 | IntermediateNodes]). 

たまたまL1とL3の両方にリンクされている場合、ヘッドノードを取り除こうとするたびに想像できますよね? したがって、リストが空の場合は、次のルールを使用できます。

transitiveSymmetricRel(L1, L2) :- transitiveSymmetricRelPath(L1, L2, []). 

しかし、私が実際に得ていないのは、transitiveSymmetricRelPath/3 の中間ノードの空でないリストをどこで取得するかということです。私は実際に与えられた事実rel(a、b)であなたのコードを試しました。rel(a,c)。また、transitiveSymmetricRel(b,c) も、transitiveSymmetricRel(c,b) も返しません。調べていただけますか?

どうもありがとう!

編集済み:次のようにルールを変更することで機能しました。

transitiveSymmetricRelPath(L2, L3, IntermediateNodes) :- symmetricRel(L1, L3),
     \+member(L3, IntermediateNodes),
     transitiveSymmetricRelPath(L1, L2, [L3 | IntermediateNodes]). 

とにかくあなたの提案をありがとう。

4

1 に答える 1

1

データのようなステートメント (最初の例の および のように) とコード (2 番目の例のように) を 1 つの名前で導入することは避けlinelineEqualくださいlineEqual。代わりに、データベースのファクトを別の名前で保持してください。次に、たとえば次のように定義できます。

areLinesEqual(L1, L2) :- linesEqual(L1, L2).
areLinesEqual(L1, L2) :- linesEqual(L2, L1).

一般に、関係がrelあり、対称推移閉包を構築したい場合は、一度に 1 つの概念を導入する必要があります。例えば:

symmetricRel(L1, L2) :- rel(L1, L2).
symmetricRel(L1, L2) :- rel(L2, L1).

transitiveSymmetricRel(L1, L2) :-
    transitiveSymmetricRelPath(L1, L2, []).

transitiveSymmetricRelPath(L1, L2, _) :-
    symmetricRel(L1, L2).

transitiveSymmetricRelPath(L1, L2, IntermediateNodes) :-
    symmetricRel(L1, L3),
    \+ member(L3, IntermediateNodes),
    transitiveSymmetricRelPath(L1, L2, [L3 | IntermediateNodes]).

(ここでは、基本的に無向グラフでパスを見つける必要があり、ループを避けるために注意する必要があることに注意してください)。あなたの場合、おそらく同じように考えることが望まれるでしょline(A, B)line(B, A)。そのためにも、別のレベルの間接化を導入する必要があります。

% to check two lines for identity
same(line(A, B), line(A, B)).
same(line(A, B), line(B, A)).

linesEqual2(L1, L2) :-
    same(L1, LI1),
    same(L2, LI2),
    (linesEqual(LI1, LI2); linesEqual(LI2, LI1)).

…対称関係の定義のlinesEqual2代わりに使用します。linesEqual

ここで難しいのは、これらすべての述語を混同しないようにするための命名スキームです…</p>

別の方法で行うこともできます。対称関係の推移閉包を求めるとすれば、それは基本的に、すべてのノード (ここでは線) のセットを分離可能なサブセットに分割することです。この洞察は、上記よりもはるかに効率的なコードを作成するのに役立ちます...しかし、これはすでにこの質問の範囲外です.

于 2012-12-29T02:26:52.413 に答える