I got an homework assignment for my logic course, but more or less don't have any clue how to solve it... With a query like
?- find(a,[r(a,[b,d]),r(b,[a,c,e]),r(c,[b]),r(d,[a,e]),
r(e,[b,d,f]),r(f,[e,g]),r(g,[f])],Path).
Prolog should return all possible paths in the given graph. The terms r(X,List) define the graph, meaning that the nodes in List can be reached from node X. In this case, the output would be:
Path = [a,b,c] ;
Path = [a,b,e,d] ;
Path = [a,b,e,f,g] ;
Path = [a,d,e,b,c] ;
Path = [a,d,e,f,g] ;
false.
Although I get the hang of the numerous solutions here on SE and on the web in general to similar problems, I'm somehow too dumb to figure out how to work with the definition of the graph in this assignment.
I figure that find(Start,...) should be called recursively with all members of the list in r(Start,List), but as a total newbie to Prolog(we just did the standard family tree stuff...) I don't know how to do that.
Any help would be really appreciated. I'm aware of the fact that I don't have much to start with, but I already spent half a night trying to figure something out and up to now I don't have a clue.
/Edit:
For starters, I think I'll need some kind of base case to abort the recursion. I think it should be either
find([],_,_).
because I guess that the last recursive call wouldn't have anything to start with, or
find(_,[],_).
assuming that the list of the terms defining adjacent nodes should be empty when the program finished processing it.
Now the actual call. Probably something like
find(Start,[r(Start,[Adjacent|Restadj])|Rest],Path):-
find(???).
My problems here are the following:
-How do I make the program use the members of the list in the r(...) term as the next Start?
-How do I check if a node has already been "visited"/ How can I remove a node from a specific list in r
-How do I put the found nodes into the Path list? Simply append? Or execute the recursive call with something like [Path|Start]?
As you see, it's not much. Some suggestive questions would be nice, since Prolog seems quite interesting and therefore fun to learn...
After spending some time with the neat PDT-Eclipse trace tool, I think I understood what the program is doing. What I dont't get at this point is why the last node always gets lost. After backtracking fails, for example because r(c,[b]) is the next found term and memberchk(b,[b]) fails because of the negation(that's what I thing + does) and no other term with r(c,X) can be found, it starts over with looking for other possibilities to go from node b, which has adjacent nodes left in r(b,[...]). But why does the program forget to put node c into the Path list? Is there a possibility to do some kind of if-then-else in case
member(r(Node, Adjacent), Graph),
member(AdjNode, Adjacent),
\+ memberchk(AdjNode, Seen),
fails, to still append the last node to Path?