6

私はプロローグが初めてで、1つの答えが見つかった後にクエリを停止する方法を試しています。私はこのコードを使用しています:

member1(L,[L|_]).                    
member1(L,[_|RS]) :- member1(L,RS),!.      

結果は次のとおりです。

| ?- member1(3,[3,2,3]).

true ? a

yes

Prolog に「true ?」の出力を停止させる方法がわかりません。代わりに「はい」と出力するだけです。if/else コンストラクトと format 関数を使用してみましたが、それでも「true ?」と出力されます。何か案は?

4

2 に答える 2

3

あなたは間違った場所を切っています。「ベースが満たされたら、それ以上バックトラックしないでください」という基本条件の後にカットします。

member1(L,[L|_]) :- !.                   
member1(L,[_|RS]) :- member1(L,RS).    

If-then は私にとってはうまくいきますが、おそらく別の方法で実装しましたか? (swi-prolog上)

member1(X,[Y|RS]) :-
    ( X = Y         -> true
    ; member1(X,RS) -> true
    ; false
    ) .

Swi には述語もありonce/1ます。

false によって指摘されたエラーを説明するために編集されました。

于 2013-11-24T22:01:32.757 に答える
2

表示された出力から、GNU Prolog を使用していると思います。しかし、最初に重要な注意事項があります。

配置したカットが意図したとおりにカットされない! 実際、答えが 1 つであることを妨げるものではありません。その証拠は次のとおりです。

| ?- member1(X,[1,2,3]).

X = 1 ? ;

X = 2

yes

したがって、まだ2つの答えがあります。経験則として: 再帰ゴールの後のカットはしばしば予期しないことをします。

正確に最初の答えが欲しい場合は、単純にonce(member(X,[1,2,3])). これonce/1も事実上のカットですが、かなり変装しています。まさに1つのことをするのは飼いならされています。はい、カットを再帰ルールに配置することもできますが、初心者の場合は後のレッスンに任せたほうがよいでしょう。

これらすべての背後には、あまり目立たないもう 1 つのポイントがあります。GNU Prolog のトップレベル シェルは、開いている代替案 (専門用語: 選択ポイント) を検出すると、さらなる解決策を求めます。したがって、GNU がさらに質問した場合、GNU はまだ調査していない部分があることを認識していますが、実際には別の答えがあるという保証はありません。

?- member(1-X,[1-a,2-b,3-c]). 

X = a ? ;

no

ここで、トップレベルは未解決の選択ポイントを認識し、クエリをさらに調査するかどうかを尋ねます。悲しいかな、この検索は無駄です...

于 2013-11-25T01:19:09.237 に答える