I'm trying to use call_with_depth_limit/3
in SWI-Prolog to implement iterative deepening and either I don't understand how it works or it's misbehaving. I have an example where the following happens:
?- 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.
According to the documentation it should succeed if the goal can be proved with Limit max recursion or less. In the first call with limit 30 we see results where the Result is 25, therefore I would expect that calling it with a limit of 26 it would succeed. I'm using constraint handling rules in the module, in case there can be some interaction there that makes it misbehave.
EDIT: After playing with Isabelle's answer I think I understand how it behaves:
- It runs a depth first search like usual but if it gets to Limit+1 depth it acts as if it failed.
- Failed branches count towards the Result.
- Every time it backtracks after a successful answer, it resets Result to the current depth of the stack.
See this example:
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.
call_with_depth_limit/3
in the comment section. Works as expected, everything is going extremely well. – Morgun