我试图call_with_depth_limit/3
在 SWI-Prolog 中使用来实现迭代深化,要么我不明白它是如何工作的,要么它行为不端。我有一个发生以下情况的示例:
?- call_with_depth_limit(mygoal, 29, Result).
Result = 29 ;
Result = 25 ;
Result = 27 ;
Result = 27 ;
false.
?- call_with_depth_limit(mygoal, 26, Result).
Result = depth_limit_exceeded ;
false.
根据文档,如果可以使用 Limit max recursion 或更少来证明目标,它应该会成功。在第一个限制为 30 的调用中,我们看到 Result 为 25 的结果,因此我希望以 26 的限制调用它会成功。我在模块中使用约束处理规则,以防那里可能存在一些使其行为不端的交互。
编辑:玩过伊莎贝尔的回答后,我想我明白它的行为方式:
- 它像往常一样运行深度优先搜索,但如果它达到 Limit+1 深度,它就像失败一样。
- 失败的分支计入结果。
- 每次它在成功回答后回溯时,都会将 Result 重置为堆栈的当前深度。
看这个例子:
loop :- loop.
succeed(0).
succeed(N) :- N > 0, N1 is N - 1, succeed(N1).
fail(N) :- N > 0, N1 is N - 1, fail(N1).
?- call_with_depth_limit(succeed(0), 1000, Result).
Result = 1 ;
false.
?- call_with_depth_limit(fail(50);succeed(0), 1000, Result).
Result = 53 ;
false.
% It tries loop until Limit+1 and therefore this is the Result
?- call_with_depth_limit(loop;succeed(0), 1000, Result).
Result = 1001 ;
false.
% In the second result it has to unroll the stack from 100 before trying the next, so Result is 100.
?- call_with_depth_limit(loop;succeed(100);succeed(0), 1000, Result).
Result = 1001 ;
Result = 103 ;
false.
?- call_with_depth_limit(loop;succeed(0);succeed(0), 1000, Result).
Result = 1001 ;
Result = 3 ;
false.
% If it gets to the end, and it has reached Limit+1 since the last successful result it returns depth_limit_exceeded.
?- call_with_depth_limit(loop;succeed(100);succeed(0);loop, 1000, Result).
Result = 1001 ;
Result = 103 ;
Result = depth_limit_exceeded.