据我了解,call_nth(:Goal,?Nth)返回目标的第N个解,但同时它秘密地计算了所有先前的解(从第1个到第(N-1)个),并忽略了它们。如果我们希望将第X个与第(X + 1)个解决方案进行比较,则介于1和N-1之间的每个X都将变得非常昂贵,因为call_nth基本上保持了在先前步骤中已经计算出的解决方案。我想知道是否有一种更有效的方法来解决这种形式的问题,而无需使用findall / 3。
(一个典型的例子是下面的脚本,如果谓词中不存在GOAL,则该脚本将找到GOAL或与其最接近的最大值。)
num(10).
num(20).
num(30).
num(40).
num(50).
search_for_goal(GOAL,RESULT):-
search_for_goal(GOAL,0,1,RESULT).
search_for_goal(GOAL,_,COUNTER,GOAL):-
call_nth(num(GOAL),COUNTER),!.
search_for_goal(GOAL,CURRENT_MAX,COUNTER,RESULT):-
call_nth(num(X),COUNTER),
COUNTER2 is COUNTER+1,
( X=<CURRENT_MAX->
search_for_goal(GOAL,CURRENT_MAX,COUNTER2,RESULT)
; search_for_goal(GOAL,X,COUNTER2,RESULT)
).
search_for_goal(_,CURRENT_MAX,COUNTER,CURRENT_MAX):-
\+call_nth(num(_),COUNTER).
答案 0 :(得分:2)
使用SWI-Prolog,可以通过Prolog引擎实现。为了说明这一点,请考虑我自己的findall / 3谓词版本,该谓词仅返回偶数解。
my_findall(Templ, Goal, List) :-
setup_call_cleanup(
engine_create(Templ, Goal, E),
get_answers(E, List),
engine_destroy(E)).
get_answers(E, [H|T]) :-
/* Skip next solution. */
engine_next(E, _),
/* Take next solution. */
engine_next(E, H),
!,
get_answers(E, T).
get_answers(_, []).
查询方式:
my_findall(X,member(X,[1,2,3,4]),Y)
仅返回n为偶数的第n个解。
Y = [2, 4]