は_639
、インスタンス化されていない匿名変数です。あなたの「事実」には、アトムではなく変数があります。例えば:
proj(A). % This has a variable A and means "any A is a project"
したがって、クエリを実行すると:
:- proj(X).
X = _blah % anonymous variable: anything is a project!
アトムが必要です:
proj(a).
proj(b).
クエリの結果は次のとおりです。
:- proj(X).
X = a ;
X = b
あなたが持っている場合:
ref(a,b).
ref(b,c).
次に、Prolog で推移的なプロパティを表現する最も簡単な方法は、ルール(またはPrologで述語と呼ばれるもの)を宣言することです。
ref(A,C) :- ref(A,B), ref(B,C).
これは、ref(A,C)
が真であればref(A,B)
真であり、ANDref(B,C)
が真であることを示しています。. クエリの実行:
:- ref(a,c).
true ;
Out of stack
または:
:- ref(a,X).
X = b ;
X = c ;
Out of stack
したがって、論理的に聞こえますが、問題があります。自己参照が原因でループに入る可能性があります。これを回避する簡単な方法は、ルール名を事実とは異なるものにすることです。
refx(A, B) :- ref(A, B).
refx(A, C) :- ref(A, B), refx(B, C).
クエリを実行すると、次のようになります。
:- refx(a, b).
true ;
no
:- refx(a, c).
yes
:- refx(a, X).
X = b ;
X = c
yes
等。
ただし、ファクトに再帰的または可換的な関係が含まれている場合は、終了の問題が発生する可能性があります。例えば:
ref(a,b).
ref(b,a).
ref(b,c).
この場合、次のクエリがrefx(a, b)
生成されます。
| ?- refx(a, b).
true ? ;
true ? ;
true ? ;
...
@lambda.xy.x が指摘しているように、これはどこに行ったかを追跡し、繰り返しの「訪問」を避けることで解決できます。
refx(X, Y) :-
refx(X, Y, []).
refx(X, Y, A) :-
ref(X, Y),
\+ memberchk((X, Y), A). % Make sure we haven't visited this case
refx(X, Y, A) :-
ref(X, Z),
\+ memberchk((X, Z), A), % Make sure we haven't visited this case
refx(Z, Y, [(X,Z)|A]).
ここで終了しrefx(a,b)
、一度成功します。
| ?- refx(a,b).
true ? ;
no
| ?-
そしてrefx(X, Y)
、すべてのソリューションを生成します(ただし、複数回成功するため、一部は繰り返されます):
| ?- refx(X, Y).
X = a
Y = b ? ;
X = b
Y = a ? ;
X = b
Y = c ? ;
X = a
Y = a ? ;
X = a
Y = c ? ;
X = b
Y = b ? ;
X = b
Y = c ? ;
(2 ms) no