prologtransitive-closure

How to get the not effect in Prolog


I am trying to create a rule that recursively calls itself, and finds all possible paths to traverse a directed graph. I am using a findall() to do so. The functions is traverse(Start,End).

I have:

traverse(Start,End,[li]) :-
   node(Start,End),
   append(End,Li).

traverse(Start,End,[Li]) :-
   node(Start,Z),
   traverse(Z,End),
   append(Start,Li).

/*here I would like to check that Z is not a member of Li before
  I call traverse(Z,End), I know I can check that it is a member
  using member(Z,Li) but how to I check it is not a member in 
  prolog*/

findalltraverses(Start,End,[list]) :-
   findall(_,traverse(Start,End).

Solution

  • Before we start: this language is called prolog.

    Your code has several mistakes/errors in different levels. Here is a (not complete) list of them:

    Ok, here is a working code snipped. The recursion end part is a bit different because it does not check if there is a edge from Start to End but asks if Start and End are the same. If so then the resulting path contains only this node. This is important because in the code snipped the path will be build when going back trough the recursion ([Start|Path]) while the list containing visited nodes grows when going into the recursion ([Start|Visited]).

    edge(a,b).
    edge(b,c).
    edge(c,d).
    edge(a,d).
    
    traverse(End,End,_,[End]).
    traverse(Start,End,Visited,[Start|Path]) :-
        edge(Start,Tmp),
        \+ member(Tmp,Visited),
        traverse(Tmp,End,[Start|Visited],Path).
    
    findalltraverses(Start,End,Out):-
       findall(List,traverse(Start,End,[],List),Out).
    

    Let's test it!

    ?- findalltraverses(a,d,Out).
    Out = [[a, b, c, d], [a, d]].
    

    Looks good.