0

I've written a predicate called find_path(S,T,Visited,Path) that can search my undirected graph and find a path from node S to node T and then return a list of edge values (the edge value is the 3rd value in the edge fact). The predicate I wrote seems to work fine, however it only returns a boolean value for the result of the search, without the list of edge values. Can someone please offer a suggestion of how I can accomplish this? Thanks in advance.

Here is my code and an image of the undirected graph I am using

enter image description here

find_path(S,T,Visited,Path) :-
    not(member(S,Visited)),         % Check that S hasnt already been visited
    direct_path(S,T,edge(S,T,D))    % Check if theres a direct path from S to T.
    ->  append(Path,[D],X)          % If so, append the edge value to Path list and end
    ;   append(Visited,[S],Y),          % If not, add S to Visited
        direct_path(S,A,edge(S,A,B)),   %   Find any edge containing S
        append(Path,[D],X),             %   Add the edge value to the path list
        find_path(A,T,Y,X).             %   Recursively call find_path again, with the new Start value

direct_path(S,T,edge(S,T,D)) :- edge(S,T,D); edge(T,S,D).

edge(1,2,7). 
edge(1,3,9). 
edge(1,6,14). 
edge(2,3,10). 
edge(2,4,15). 
edge(3,4,11). 
edge(3,6,2). 
edge(4,5,6). 
edge(5,6,9).
lurker
  • 56,987
  • 9
  • 69
  • 103
Uncle_Timothy
  • 101
  • 1
  • 2
  • 10
  • 1
    Predicates don't return anything. They either succeed, fail, or don't terminate (bad behavior). If you want to return the list of edge values, you need to pass it through an argument to your predicate that would build the desired list in. Note that `,` has higher precedence than `;`. Your logic for `find_path` isn't executing the way you think it is. You need to group things with parentheses. Otherwise, for example, if `direct_path(S,T,edge(S,T,D))` succeeds, you'll just call `append(Path, [D], X)` but `X` isn't used anywhere else in that logical leg. – lurker Aug 29 '17 at 16:45
  • See [this](https://stackoverflow.com/q/30328433/772868) for a general solution. – false Aug 29 '17 at 19:01
  • Thanks for your reply. How would I pass each edge value it through the Path argument? – Uncle_Timothy Aug 30 '17 at 03:03
  • Very generically speaking, if you want to build a list, one pattern in Prolog is: `my_predicate(..., [Edge | Edges]) :- ....(some stuff here) ..., my_predicate(..., Edges).` and somewhere along the line, a base case that looks like `my_predicate(..., []).`. – lurker Aug 30 '17 at 10:11
  • Another common pattern uses an auxiliary predicate: `my_predicate_aux(..., EdgesSoFar, Edges) :- ...(some stuff here) ..., my_predicate_aux(..., [Edge | EdgesSoFar], Edges).` with a base case that looks something like `my_predicate_aux(..., Edges, Edges).` and with the whole thing started with a main predicate, `my_predicate(..., Edges) :- my_predicate_aux(..., [], Edges).` – lurker Aug 30 '17 at 10:15
  • As I mentioned, you have a couple of other serious issues. One being the improper grouping of your `,` versus `;`, and the other being singleton variable `X`, whose result gets thrown away when the predicate completes its query. You probably have enough arguments in your predicate, you just aren't using them properly. If you want to find a path from `S` to `T`, you'd start with `path_from_to(S, T, Path)` and then have an auxiliary, `path_from_to(S, T, Visited, Path)`, ultimately `Path` being the list of nodes in the desired path. – lurker Aug 30 '17 at 13:55
  • Thanks so much for your help Lurker, I used the auxiliary and was able to make it work how I wanted it! – Uncle_Timothy Aug 31 '17 at 11:44

0 Answers0