Reputation: 1759
I have a prolog program with searches for something and every time it hasn't found it, it increments a variable by 1. If it never finds what the user is searching for, it will search forever. Can I stop prolog from doing that, if a special variable is reached? This is the predicate which searches for something:
% ---------------------------------------------------------------------
% find(X,Y,N) :- ...search for it
% find(X,Y,N) :- ...if not found, increment N by 1 and repeat recursion
% ---------------------------------------------------------------------
find(Y,I,G) :- member(Y,I), G is 0.
find(Y,I,G) :- not(member(Y,I)), expand(I,O), find(Y,O,G1), G is G1+1.
find(Y,I,50) :- fail.
So I want to write something like
find(X,Y,50) :- return false
So that the program returns false, if it hasn't found it after 50 recursions. How do I realize that?
EDIT: This is my code: http://pastebin.com/4X7BSFQ2
vwg(X,Y,G)
is searching if the two persons X and Y are related with grade G
for example:
vwg(vanessaMueller, selinaMueller, 1)
is true, cause vanessaMueller is her mother
Upvotes: 1
Views: 4716
Reputation: 74227
If you always have the third argument (the iteration count) bound, you can simply count down. Once you hit zero, you've failed:
find( Y , I , G ) :- %
integer(G) , % enforce the contract that G must be bound
G > 0 , % if we've not yet hit zero,
member(Y,I) , % see if we can find Y in I
! . % and eliminate any alternatives.
find( Y , I , G ) :- %
integer(G) , % enforce the contract that G must be bound
G > 0 , % if we've not yet hit zero
G1 is G-1 , % decrement G
expand(I,I1) , % expand I
find(Y,I1,G1) % and recurse down
. %
Note that the above requires the initial call to to find/3
to have its third argument bound to an integer.
If, instead, you want your third argument to return the count, rather than defining a limit (and using a hard-coded limit instead), you can use a helper with an accumulator:
find( Y , I, G ) :-
find(Y,I,1,G)
.
find( Y , I , G , G ) :-
G =< 50 , % if we've not yet exceeded the limit
member(Y,I) , % see if we can find Y in I
! . % and eliminate alternatives
find( Y , I , T , G ) :- %
T < 50 , % if we're below the limit
T1 is T+1 , % increment the accumulator
expand(I,I1) , % expand I
find(Y,I1,T1,G) % and recurse down.
. % easy!
Or you can pass in the limit another argument and get the recursion count on success:
find( Y , I, N , G ) :-
find(Y,I,N,1,G)
.
find( Y , I , N , G , G ) :-
G =< N ,
member(Y,I) ,
! .
find( Y , I , N , T , G ) :-
T < N ,
T1 is T+1 ,
expand(I,I1) ,
find(Y,I1,N,T1,G)
.
There's more than one way to do it.
Upvotes: 1
Reputation: 60014
from your pastebin, I get
find(Y,I,G) :- member(Y,I), G is 0.
find(Y,I,G) :- not(member(Y,I)), expand(I,O), find(Y,O,G1), G is G1+1.
find(Y,I,50) :- fail.
I would try
find(Y,I,0) :- member(Y,I).
find(Y,I,G) :- G < 50, not(member(Y,I)), expand(I,O), G1 is G+1, find(Y,O,G1).
Upvotes: 1