Search code examples
multithreadinglistrecursionprolog

Prolog find all paths Implementation


I've been tasked to implement a version of findall in Prolog without using any Prolog built-ins except for not and cut - so basically in pure Prolog.

I'm trying to search a tree for all direct descendants and return the results in a list

parent(a, b).
parent(b, c).
parent(b, d).
parent(e, d).

What I have so far is:

find(X, L) :- find2(X, [], L).
find2(X, Acc, L) :- parent(Y, X), find2(Y, [Y|Acc], L).
find2(_, Acc, Acc).

What I want to be getting when I enter for example:

find(a,X).

would be:

X = [b, c, d]

(Order not important)

However instead I am getting:

X = [b, c] ;
X = [b, d] ;
X = [b] ;
X = [].

I'm new to Prolog so any help on this would be much appreciated.

Thanks


Solution

  • Thanks for you help everyone. I managed to solve it in the end by adding a predicate which checked each item against the current list, and failed if it was already present:

    find(X, Loa) :- find(X, [], Loa), !.
    find(X, Acc, Loa) :- dec(X, Y), uList(Y, Acc, AccNew), find(X, AccNew, Loa).
    find(_, Acc, Acc).
    
    dec(X,Y) :- parent(X,Y).
    dec(X,Y) :- parent(X,Z), dec(Z,Y).
    
    uList(X, [], [X])  :- !.
    uList(H, [H|_], _) :- !, fail.
    uList(X, [H|T], L) :- uList(X, T, Rtn), L = [H|Rtn].