2

私はfindallProlog に代わるものを作成しようとしています。

私が持っているものは次のとおりです。

solutions(A,T,S) :- 
   T,
   assert(temp(A)),
   fail.
solutions(A,T,S) :-
   obtain([],S).

obtain(X,S) :-
   retract(temp(A)),
   obtain([A|X],S).
obtain(S,S).

ただし、これにより一貫性のない結果が得られます。なにが問題ですか?前もって感謝します。

4

2 に答える 2

0

これを試してみてください。retract/1 の後にカット (!) を実行し、明示的に assertz/1 をアサートします。

solutions(A,T,_) :- 
   T,
   assertz(temp(A)),
   fail.
solutions(_,_,S) :-
   obtain(S).

obtain([A|S]) :-
   retract(temp(A)), !,
   obtain(S).
obtain([]).

正常に動作しますが、再入可能ではありません。2 番目のクエリ結果は間違っています。

?- solutions(X,between(1,3,X),L).
L = [1, 2, 3].

?- solutions(X-R,(between(1,3,X),solutions(Y,between(1,X,Y),R)),L).
L = [3-[2-[1-[1], 1, 2], 1, 2, 3]].

編集 08.11.2020:
gensym/2 を使用したリエントラント ソリューションは次のとおりです。

solutions(A,T,L) :-
   setup_call_cleanup(
      gensym('bag',B),
      solutions(B,A,T,L),
      retractall(temp(B,_))).

solutions(B,A,T,_) :- 
   T,
   assertz(temp(B,A)),
   fail.
solutions(B,_,_,S) :-
   obtain(B,S).

obtain(B,[A|S]) :-
   retract(temp(B,A)), !,
   obtain(B,S).
obtain(_,[]).

両方のクエリが正常に機能するようになりました。

?- solutions(X,between(1,3,X),L).
L = [1, 2, 3].

?- solutions(X-R,(between(1,3,X),solutions(Y,between(1,X,Y),R)),L).
L = [1-[1], 2-[1, 2], 3-[1, 2, 3]].

警告:論理的な更新セマンティクスを備えた Prolog システムは、
retract/1 を繰り返し実行すると非効率になる可能性があります。

于 2020-11-08T20:45:40.160 に答える