Reputation: 777
I have a predicate that is bi-directional and tells, whether one node is connected to another. E.g.
has(a, b).
has(b, c).
has(d, b).
Now I would like to list all nodes which can be reached (from a specific node) with a given number of steps.
connected_nodes(a, T, 2).
should therefore output
T = c
T = d
My current code looks like this:
connected_nodes(A, B, 0) :- write(A).
connected_nodes(A, B, N) :-
N > 0, M is N - 1,
has(A, X),
connected_nodes(X, B, M).
This works for T = c but not for T = d, as this is a bi-directional relation.
Am I thinking correctly in terms of recursion or how in which other way does this problem have to be solved?
Upvotes: 0
Views: 560
Reputation: 22255
Your connected
predicate seems fine. It might have made more sense to make the base case rely on has
, but it's up to you.
However, you say your has
predicate is "bi-directional" but you haven't explicitly created a rule that indicates this.
The following code is a "bi-directional" version of your code:
has(a, b).
has(b, c).
has(d, b).
bi_has(X,Y) :- has(X,Y).
bi_has(X,Y) :- has(Y,X).
connected_nodes(A, B, 0) :- write(A).
connected_nodes(A, B, N) :-
N > 0, M is N - 1,
bi_has(A, X),
connected_nodes(X, B, M).
Note however that your query now returns a
as a possible answer too. This makes since, because you never explicitly stated you don't want to return back to the same element after 2 steps.
If you don't want this behaviour, then you need to also keep a list of elements visited so far (i.e. an accumulator), and confirm that you're not revisiting elements.
Upvotes: 1