7

リストのメンバーシップを決定するための標準的な手順があります。

member(X, [X|_]).  
member(X, [_|T]) :- member(X, T).

私が理解していないのは、次のクエリを実行する理由です。

?- member(a,[a,b]).

結果は

True;  
False.

最初のルール(aはリストの先頭であるため)を使用して目標を達成すると、Trueが返され、それがifの終わりになると思いました。次に、2番目のルールを使用して目標を達成しようとして失敗したように見えますか?

PrologインタープリターはSWI-Prologです。

4

3 に答える 3

7

最初に同様のクエリを考えてみましょう:[編集:独自の定義を追加せずにこれを実行します; member/2すでに定義されています]

?- member(a,[b,a]).
true.

この場合、最適な答えが得られます。解決策は1つだけです。しかし、リスト内の要素を交換すると、次のようになります。

?- member(a,[a,b]).
true ;
false.

論理的には、どちらもクエリが真であるという単なる肯定です。

違いの理由は、2番目のクエリで、リストの要素としてtrue見つかった直後に回答が与えられるためです。a残りのリスト[b]には適切な要素が含まれていませんが、これはまだ調査されていません。要求(ヒットSPACEまたは;)があった場合にのみ、リストの残りの部分が試され、それ以上の解決策はありません。

基本的に、この小さな違いは、計算が完全に終了したときと、まだやるべきことがあるときのヒントを提供します。単純なクエリの場合、これは違いを生みませんが、より複雑なクエリでは、これらのオープンな選択肢(選択ポイント)が蓄積され、メモリを使い果たす可能性があります。

古いトップレベルは、解決策がなかったとしても、それ以上の解決策を見たいかどうかを常に尋ねてきました。

編集:

次の答えがない場合にそれを求めないようにする機能は、実装の詳細に大きく依存します。同じシステム内で、同じプログラムがロードされている場合でも、異なる結果が得られる可能性があります。ただし、この場合、SWIの組み込み定義member/2を使用していましたが、組み込み定義を上書きする独自の定義を使用しました。

SWIは、次の定義を組み込みとして使用します。これは、論理的には同等ですが、SWIにとって不要な選択ポイントを回避しやすくなりますが、他の多くのシステムはこれから利益を得ることができません。

member(B, [C|A]) :-
        member_(A, B, C).

member_(_, A, A).
member_([C|A], B, _) :-
        member_(A, B, C).

さらに複雑にするために:多くのプロローグには異なるトップレベルがあり、クエリに変数が含まれていない場合、それ以上の回答を要求することはありません。したがって、これらのシステム(YAPなど)では、間違った印象を与えます。

これを確認するには、次のクエリを試してください。

?- member(X,[1]).
X = 1.

SWIは、これが唯一の答えであると再び判断できます。しかし、たとえば、YAPはそうではありません。

于 2013-01-30T02:00:27.143 に答える
2

「;」を使用していますか 最初の結果の後に演算子を押してからリターンを押しますか?これは、クエリにさらに結果を探すように求めていると思いますが、結果がないため、falseとして表示されます。

于 2013-01-30T01:05:53.613 に答える
1

Prologのカットについて知っていますか- !

member(X, [X|_]).Prologに変更した場合member(X, [X|_]) :- !.、最初の解決策の後に別の解決策を見つけようとはしません。

于 2013-01-30T02:37:47.220 に答える