Rahul
Rahul

Reputation: 47

Stopping recursion in Prolog?

connect(raj,isa,indian).
connect(indian,isa,man).

attribute(raj,marks,100).
attribute(indian,marks,200).

p(Node,marks,Number) :- 
   attribute(Node,marks,Number).
p(Node,marks,Number) :-
   connect(Node,isa,X),
   p(X,marks,Number).

So now, while querying,

171 ?- p(raj,marks,100).
true .

172 ?- p(raj,marks,200).
true .

In this case, I want p(raj,marks,200) to fail.

How do I stop recursion while getting the first answer?

Upvotes: 2

Views: 2257

Answers (1)

lurker
lurker

Reputation: 58244

I suppose you're wanting Prolog not to prompt for more solutions after confirming these examples are true? You could potentially do this with a cut, since the cut prunes the backtracking at a certain point:

p(Node, marks, Number) :- 
   attribute(Node, marks, Number),
   !.                       % Don't backtrack after confirming the attribute
p(Node, marks, Number) :-
   connect(Node, isa, X),
   p(X, marks, Number).

Now your queries as stated will not backtrack, as I think you're asking, after confirming the solutions:

| ?- p(raj, marks, 100).

yes
| ?- p(raj, marks, 200).

(1 ms) yes
| ?-

But this presents a problem. Your predicate will no longer find all valid solutions to the query, p(raj, marks, X). It will stop after finding only one, even though there are more.

| ?- p(raj, marks, X).

X = 100

yes
| ?-

If we take the cut back out of the code (going back to your original code), it gives the correct response with all of the valid solutions for X:

| ?- p(raj, marks, X).

X = 100 ? ;

X = 200 ? ;

no
| ?-

Another option to get the result you're after is to use the once/1 predicate, which will only seek the first solution and then stop backtracking:

| ?- once(p(raj,marks,100)).

(1 ms) yes
| ?-

Now, we haven't broken the p/3 query and have a way to get the first solution without a backtrack. You could build a separate predicate around this if you wish:

p_once(Node, Marks, Number) :- once(p(Node, Marks, Number)).

And then, of course:

| ?- p_once(raj,marks,100).

(1 ms) yes
| ?-

But using once/1 explicitly is preferred, in my opinion, since it is concise and makes the intention clear, while preserving the integrity of your original predicate.

Upvotes: 5

Related Questions