Альтернатива для поиска
Я пытаюсь создать альтернативу findall
в прологе.
Что у меня есть:
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).
Это, однако, дает мне противоречивые результаты. Что случилось? Заранее спасибо.
1 ответ
Есть несколько проблем с вашей реализацией.
Там нет очистки в начале. добавлять
retractall(temp(_))
доT,
obtain/2
удастся получить много разных ответов, потому чтоretract(temp(A))
даст много ответов, и потому что второй пунктobtain(S,S)
всегда будет решением. Это можно сохранить, добавив разрез послеretract
,|?- получить ([],S). S = [2,1]?; S = [1]?; S = [2]?; S = []?; нет
Вы можете изменить порядок, либо с помощью
asserta/1
или путем переопределенияobtain/2
,Ваше определение не является повторным. Это не может быть решено легко. Вам понадобится либо немного
gensym
как функциональность или некоторые даже более продвинутые функции.Для мелкого шрифта
assert/1
противassertz/1
увидеть этот ответ.
Попробуйте это, сделав вырез (!) После 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([]).
Работает нормально, но не повторяется, второй результат запроса неверен:
?- 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 с семантикой логического обновления
может быть неэффективной во время многократного отзыва /1.