Reputation: 3112
I tried to write a simple Prolog program with the following ruleset.
conc([],L,L).
conc([X|L1],L2,[X|L3]):- conc(L1,L2,L3).
Then I loaded this in the SWI-Prolog shell and executed the following query in the trace mode.
?-conc([2,3],[p,q],[2,3,p,q]).
The output was as follows.
[trace] ?- conc([2,3],[p,q],[2,3,p,q]).
Call: (8) conc([2, 3], [p, q], [2, 3, p, q]) ? creep
Call: (9) conc([3], [p, q], [3, p, q]) ? creep
Call: (10) conc([], [p, q], [p, q]) ? creep
Exit: (10) conc([], [p, q], [p, q]) ? creep
Exit: (9) conc([3], [p, q], [3, p, q]) ? creep
Exit: (8) conc([2, 3], [p, q], [2, 3, p, q]) ? creep
true.
Now the problem is to draw the derivation tree of this goal, but I can't exactly understand how prolog does this, even by looking at the trace
output above.
Can someone explain the derivation tree of the above query with regard to the mentioned ruleset? Helpful answers are highly appreciated.
Upvotes: 1
Views: 279
Reputation: 15316
I feel that using the tracer is generally unhelpful unless you already know what you are doing and know that there is a problem at a precise location and even then it's a hard-to-disentangle mess.
It's much better to look closely at the program, and read it as the definition of a recursive call (or alternatively, as an inductive definition):
[]
and some other list L
is that same list L
: conc( [], L, L ).
X
and some other list L2
is a list which is starting with that same X
and continuing with a list L3
such that:
L3
is the concatenation of lists L1
and L2
: conc( [X | L1], L2, [X | L3] ) :-
conc( L1, L2, L3 ).
This is a pretty good actionable definition of concatenation:
conc(A1,A2,R)
succeeds, then we certainly have that all the element of A1
followed by all the elements of A2
form R
(and so the definition makes sense as "concatenation").conc
"refers to itself" (recursively) the first list argument is smaller by one, so we have a "variant" that is monotonically decreasing and are getting somewhere (we will also automatically stop because a list length is always >= 0).conc([],L,L).
was missing we would stop but fail due to lack of a matching clause for an empty list).The "derivation tree" is rather linear (and not different from a derivation that you would find in a functional language), i.e. apply the second clause recurisvely until it no longer applies, then apply he first clause.
And thus we see:
Call: (8) conc([2, 3], [p, q], [2, 3, p, q])
Call: (9) conc([3], [p, q], [3, p, q])
Call: (10) conc([], [p, q], [p, q])
Exit: (10) conc([], [p, q], [p, q])
Exit: (9) conc([3], [p, q], [3, p, q])
Exit: (8) conc([2, 3], [p, q], [2, 3, p, q])
Note the traditional name of the "Exit port". The correct name is and should have always been "Success", even back in the 1980s. It never got changed.
Upvotes: 1
Reputation: 5509
The derivation tree is the following (considering clauses with renamed variables):
Upvotes: 2
Reputation: 683
?- conc([2,3],[p,q],[2,3,p,q]).
Call: (8) conc([2, 3], [p, q], [2, 3, p, q]) ? creep
The current goal is the question.
Since [2,3]
does not match []
, rule 1 is no option, thus rule 2 is tried.
To match the head of rule 2, these substitutions are made: X/2, L1/[3], L2/[p,q], L3/[3,p,q]
.
Our new goal is now the body of rule 2, conc(L1,L2,L3)
, after the substitutions above, that is conc([3],[p,q],[3,p,q])
.
Call: (9) conc([3], [p, q], [3, p, q]) ? creep
Since [3]
does not match []
, rule 1 is no option, thus rule 2 is tried.
Substitutions: X/3, L1/[], L2/[p,q], L3/[p,q]
Our new goal is now conc(L1,L2,L3) after the appropriate solutions, which amounts to conc([],[p,q],[p,q])
.
Call: (10) conc([], [p, q], [p, q]) ? creep
Matches rule 1 => proof suceeded
Thus, the to-do-list for goal 10 is proven, thus goal 10 is proven:
Exit: (10) conc([], [p, q], [p, q]) ? creep
Thus, the to-do-list for goal 9 is proven, thus goal 9 is proven:
Exit: (9) conc([3], [p, q], [3, p, q]) ? creep
Thus, the to-do-list for goal 8 is proven, thus goal 8 is proven:
Exit: (8) conc([2, 3], [p, q], [2, 3, p, q]) ? creep
Since goal8 was the question, we're done, the proof is complete:
true.
Upvotes: 1