How to make Prolog explain your result outside of the true statement
I have the following facts and rules:
flight(sea,msp).
flight(msp,jfk).
route(A,B) :- flight(A,B).
route(B,A) :- flight(A,B).
route(A,C) :- flight(A,B) , flight(B,C).
when the request for route(sea,jfk)
I get the result true
, but I want to get an explanation:
sea-->msp-->jfk
thus I can say not only that it is true, but also how it is true.
source to share
You keep track of which nodes in your graph you have already visited. You need to do this anyway, as you need to detect the loops in your graph so you don't fall into the rabbit hole of infinite recursion.
And in Prolog, we use helper methods that carry state in the form of 1 or more additional arguments. A commonly used convention is to have a "public" predicate - say route/3
, which invokes a "private" working predicate that has the same name with a higher degree, for example route/4
. Something like this should do you:
route( A , B , R ) :- % find a route R from A to B
route(A,B,[],R) % - by invoking a worker, seeding its list of visited nodes with the empty list
. % Easy!
route(B,B,V,R) :- % we've arrived at the destination (B) when the origination node is the same as the destination node.
reverse([B|V],R) % - just reverse the list of visited nodes to get the routing.
. %
route(A,B,V,R) :- % otherwise...
flight(A,T) , % - if there an edge out of the current node (A) ,
\+ member(T,V) , % - to an as-yet unvisited node...
route(T,B,[A|V],R) % - go visit that node, marking the current node as visited.
. % Easy!
source to share
So, you want to get from A
to B
, but not only that, you also want to know the list of stations on your route.
Be sure to carefully study the following two related questions and the answers suggested to the question:
The meta predicates provided in the links above allow you to delegate recursion processing to a solid, validated, reusable component. More time to focus on other parts of the solution!
source to share
This is something that depends a lot on your prologue system. Since you marked it as swi, I'll give you a specific SWI answer.
You can start the tracer. Using trace/0
:
?: trace.
true
[trace]?:
When you enter your query now, you can see all calls, exits, failure and retry of the predicate. However, you cannot see the variable names in the command line tracer. To see what actions you can take, you can enter h
. The most interesting are probably n
for the next step and f
for completing the current goal.
Or use trace/1
and trace/2
for the withdrawal of the call stack:
?: trace(flight/2). % calls, exits, fails and redos are output for flight/2
?: trace(route/2, +exit). % only exits are output for route/2.
If you also have xpce installed, you can use gtrace/0
for the GUI.
If you want to access your route from the prologue, you can also write a new route/3
one that also lists the ways.
So, for your case, you can make the following request:
?- trace(flight/2,+exit).
% flight/2: [exit]
true.
[debug] ?- route(sea,jfk).
T Exit: (7) flight(sea, msp)
T Exit: (7) flight(msp, jfk)
true.
source to share