what does the follow prolog codes do? - prolog

I am having trouble understanding the codes below.
Can someone explain step by step what is happening if I have the follow input:
append([1,2,3], Lst).
Actually, I don;t get how 1 and 2 is appended the list Lst as a result.
append([_], []).
append([H|T], [H|N]) :- append(T,N).

It sounds like you're new to Prolog. If so, welcome! Let's analyze this.
This unfortunately-named function has two clauses. Prolog looks at the clauses in order to see which one applies. When it finds one that matches, it tries to perform it. If there's a failure somewhere in performing it, it will back up and try the next option. Where precisely these choice points are varies depending on the program; in this program, the only one will be at the clause level, deciding which rule to use.
One way of looking at the first rule is that it is saying "A list with one element, regardless of what that element is, is related to the empty list." Looking at append([_], []), if we had X = [foo] and Y = [], it would hold, because [foo] is a one-item list and [] is the empty list. This rule is good Prolog style, because it will work regardless of instantiation: we could supply the left or the right or neither, it doesn't matter.
The second clause is also quite simple. It says that the left argument and the right argument are related if they both start with the same item, and if the rest of the lists are also related by this same predicate. In other words, if I have two lists X and Y such that append(X, Y) is true, then append([H|X], [H|Y]) is also true. It doesn't matter what H is and it doesn't matter what X and Y are, except insofar as would be implied by append/2.
Thinking logically, if I know that any one-item list is related to the empty list, and any list is related to a list that starts with the same item and otherwise is the same, the only kinds of lists that can be so related are lists where every item is the same, except the left list has one more item in it at the end which is not present on the right. So [1,2,3,4] is related to [1,2,3], but so is [1,2,3,foo] and [1,2,3].
Procedurally, let's look at what happens as this predicate is processed with this set of arguments:
append([1,2,3], X).
The first rule won't match on [1,2,3]. So we must look at the second rule:
append([1|[2,3]], [1|X]) :- append([2,3], X).
We can repeat:
append([2|[3]], [2|Y]) :- append([3], Y).
Now the first rule does match:
append([3], []).
So putting it all together:
append([1,2,3], [1|X]) implies
append([2,3], X=[2|Y]) implies
append([3], Y=[])
so Y = []
so X = [2]
so the right side is [1,2].
A Prolog trace will show you basically the same information:
?- trace, append([1,2,3], X).
Call: (7) append([1, 2, 3], _G1633) ? creep
Call: (8) append([2, 3], _G1752) ? creep
Call: (9) append([3], _G1755) ? creep
Exit: (9) append([3], []) ? creep
Exit: (8) append([2, 3], [2]) ? creep
Exit: (7) append([1, 2, 3], [1, 2]) ? creep
What makes this Prolog code confusing is that it doesn't look like you've told Prolog how to do anything. And it's true, you haven't, but by specifying what is true logically, Prolog is able to figure it out by itself. This is pretty clever code. If this were Haskell, we'd be talking about the built-in function init, which returns all of the list but the last item.
Hope this helps!

Related

Calling phrase/2 on a list of grammar rules, rather than a list of atoms

With a grammar like this:
as --> [].
as --> [a], as.
b(b(a)) --> as.
c(X) --> b(X).
phrase(b(X), [a, a]) & phrase(c(X), [a, a]) work no problem. Both return X = b(a)..
But is it possible to unify something like this?
phrase(c(X), [b(a)]).
OR:
phrase(c(X), [b(b(a))]).
I've had no luck, though it seems like it should be possible. I think this means I have some misunderstanding about DCGs. I know they work through difference lists, and succeed when they can apply a series of rules to consume all the elements of the list. Is there something special about atoms or tokens as far as phrase/2 is concerned?
Here's what the trace looks like:
[trace] [4] ?- phrase(c(X), [b(a)]).
Call: (5,411) c(_57162, [b(a)], []) ? creep
Call: (5,412) b(_57162, [b(a)], []) ? creep
Call: (5,413) [b(a)]as[] ? creep
Fail: (5,413) [b(a)]as[] ? creep
Fail: (5,412) b(_57162, [b(a)], []) ? creep
Fail: (5,411) c(_57162, [b(a)], []) ? creep
false.
The failure at [b(a)]as[] is interesting to me. What is being tested there? And... what does that syntax mean?
I know some people find it easier to answer a question when they understand a little more about what I'm actually trying to accomplish, so:
Occasionally in my application I'd like to rephrase inelegant sentences. For instance, sometimes I'll come across something like ["bake", "that" "many", "pie", "plus", "one"]. I'd like the DCG to treat this as though it'd encountered ["bake", "x", "pie"] instead. So I could use phrase(foo(X), ["x", "pie"]), and if that succeeds, then I might like to wrap it in another rule higher up in the grammar. (Why not just call the higher rule to start? Some of the higher rules are very slow in my grammar, so I'm trying to "fail quickly" by testing a lower-level grammar rule first.)
Thanks in advance for any advice!
Let's align the grammar rules to better show what they mean.
Note that they are doing list processing and consume the elements within brackets if those unify with the prefix of the list. (conversely, they may generate the elements within brackets if your run the DCG "in reverse")
as --> []. % consumes nothing
as --> [a], as. % consumes an atom 'a', then calls rule as//0
b(b(a)) --> as. % consumes nothing, then calls rule as//0
c(X) --> b(X). % consumes nothing, then calls rule b//1
The arguments within parentheses are standard Prolog predicate arguments.
When you call
phrase(b(X), [a, a])
This is a successful path through the tree of possibilities:
Use b(X) to consume a prefix of [a,a]:
X is unified with b(a) and as//0 is called, nothing is consumed.
Use the second clause of as to consume a prefix of [a,a]:
a is consumed and as//0 is called
Use the second clause of as to consume a prefix of [a]:
a is consumed and as//0 is called
Use the first clause of as to consume a prefix of []:
Succeeds without further rule calls
Thus the phrase/2 call succeeds with X=b(a), but the b(a) has nothing nothing to do with the b and a of the rules.
What about phrase(c(X), [b(a)]).?
Use c(X) to consume a prefix of [b(a)]:
Nothing is consumed, b(X) is called.
Use b(X) to consume a prefix of [b(a)]:
-X is unified with b(a) (of the head, not of the list), nothing is consumed, as is called.
Use as to consume a prefix of [b(a)]:
The first clause applies as it consumes nothing, but going down that path eventually will result in failure as we used phrase/2, demanding that the list be empty on success (rather than phrase/3 where we could leave a Rest argument unbound).
The second clause does not apply as it consumes a but the list is [b(a)]
Failure.
Similarly for phrase(c(X), [b(b(a))]).
The tracer output:
Call: (5,413) [b(a)]as[] ? creep
Fail: (5,413) [b(a)]as[] ? creep
seems to indicate that, via the only rules that applies, namely the first:
as --> [].
the actual list content [b(a)] must be equal to [] (because due to the phrase/2 call we want to have an empty "rest"). You may be seeing an effect of the optimizer.
The strange output of the tracer seems to be due to the fact that - at least in my swipl - as is declared as an infix operator :-)
proof:
?- current_op(Prec,Type,as).
Prec = 700,
Type = xfx.
Renaming your predicate to something else - I chose asif for now - changes the output of the tracer:
?- trace, phrase(c(X), [b(b(a))]).
^ Call: (9) phrase(c(_5760), [b(b(a))]) ? creep
Call: (12) c(_5760, [b(b(a))], []) ? creep
Call: (13) b(_5760, [b(b(a))], []) ? creep
Call: (14) asif([b(b(a))], []) ? creep
Fail: (14) asif([b(b(a))], []) ? creep

Prolog: Say how Prolog responds to the inquiry and draw a search tree for it ?- member(2, [2, a, X])

How will Prolog respond to the following inquiry? Draw a search tree for the inquiry, too.
?- member(2, [2, a, X]).
So first of all, what does this inquiry mean?
Let's take another more clear example:
?- member(vincent,[yolanda,trudy,vincent,jules]).
Prolog will check if vincent is in the list. It checks one by one, so it will first compare vincent and yolanda. No match, now recursive rule aka go to second clause. Now it looks like that:
?- member(vincent,[trudy,vincent,jules]).
vincent and trudy, no match. Recursive rule:
?- member(vincent,[vincent,jules]).
vincent and vincent, match! So return true.
Back to our example. Prolog will immediately return true as 2 is in the list (namely the head of it).
But how will the search tree look like? I really have no idea and I'm scared they will ask me to draw a search tree in the test...
That query means
For which X is 2 an element of the list [2, a, X]?
Well, let's see how Prolog answers this:
?- member(2, [2, a, X]).
true
; X = 2.
The first answer we get is true which is the empty answer substitution. It means here that 2 is a member of that list for any X. Really any! Can this be true?
?- X = any, member(2, [2, a, X]).
X = any
; false. % that is no solution
It's even true for any!
Now back to the original query: The second answer is a simple solution X = 2. So Prolog tells us that also 2 might be such an element. Alas, we already know that, for we know that this holds for any term. And thus also 2. Therefore, the second answer is redundant.
You can avoid many such redundancies by using memberd/2 instead!
As for the search tree, member/2 always visits the entire list. One solution after the other. So the search tree only depends on the number of elements in the list.

Prolog - How do I get the tail to not be null

I have the following problem:
Define a predicate sorted(LL), that is satisfied when the list LL
contains other lists that are sorted in order of increasing length.
For example:
?- sorted([[],[1],[1,1],[1,1,1]]) -> yes.
?- sorted([[],[1],[1,1]]) -> yes.
?- sorted([[1],[],[1,1],[1,1,1]]) -> no.
And I have this code so far:
% shorter/2
shorter([],_).
shorter([_|T1], [_|T2]) :- shorter(T1,T2).
% sorted/1
sorted([]).
sorted([_]).
sorted([L1,L2 | T]) :- shorter2(L1, L2), sorted([L2,T]).
The problem is contained in the above line: sorted([L2,T]). When only one element is left in the list of lists, that call will append an empty list [] because of which shorter/2 will fail. It is depicted in the following SWIPL trace.
[trace] ?- sorted([[1],[2,3]]).
Call: (6) sorted([[1], [2, 3]]) ? creep
Call: (7) shorter2([1], [2, 3]) ? creep
Call: (8) shorter2([], [3]) ? creep
Exit: (8) shorter2([], [3]) ? creep
Exit: (7) shorter2([1], [2, 3]) ? creep
Call: (7) sorted([[2, 3], []]) ? creep <-- empty list appended
Call: (8) shorter2([2, 3], []) ? creep
Fail: (8) shorter2([2, 3], []) ? creep
Fail: (7) sorted([[2, 3], []]) ? creep
Fail: (6) sorted([[1], [2, 3]]) ? creep
#PauloMoura already gave you the right answer. Is there anything to learn about this? How did you encounter that problem? And how can you locate such problems systematically? I assume that you did not jump into the debugger to look at all those traces for sheer curiosity and a low on supply of animated gifs.
You rather encountered a problem. That is, you had the goal sorted([[1],[2,3]]). which you expected to succeed, but it did not. So you had here some unexpected failure. Sometimes also called insufficiency or incompleteness. This means that the definition for sorted/1 is too specialized, it describes a set of solutions that is too small — at least it misses sorted([[1],[2,3]]).
It often helps to minimize the problem, first. Also sorted([[],[3]]) fails, although we expect it to succeed. And sorted([[],[]]) even loops.
Understanding non-termination
Loops? That's often even easier to localize in a pure Prolog program. I will add goals false and goals like T = [] into the program. The resulting program fragment (called a failure slice) certainly will become completely dysfunctional. But it will retain a very nice property. For: if this new fragment loops, then also the original program will loop. Here is that program that still loops:
?- sorted([[],[]]), false.
sorted([]) :- false.
sorted([_]) :- false.
sorted([L1,L2 | T]) :- T = [], L1 = [], L2 = [],
shorter(L1, L2),
sorted([L2,T]).
shorter([],_).
shorter([_|T1], [_|T2]) :- false,
shorter(T1,T2).
in other words:
sorted([[],[]]) :-
shorter([],[]),
sorted([[],[]]).
So, procedurally speaking, that rule does not (always) reduce the length of the list.
Concluding reading
Another way to understand the problem is to read the recursive rule right-to-left in the direction the arrow is pointing. Actually, :- is meant to symbolize ←, well, 1970s style (listen to this French 1972 summerhit to until you understand). So let's try this. I will read:
sorted([L1,L2 | T]) :- shorter2(L1, L2), sorted([L2,T]).
^^^^^^^^^^^^^^ starting here
I start on the right side and interpret this as:
Provided, sorted([L2,T]) is true.
Maybe some extra remark: Now, you might get pretty uneasy. You might say: Who knows this? Maybe that is not true at all! But the point is, it's just conditional. OK?
and provided shorter(L1, L2) is true
then, we can conclude that sorted([L1, L2|T]) is true.
So we take a list of length 2 as granted and conclude that a list of length 2 or more holds as well.
But where do we actually state that a list of length 2 holds? There is no other place than this rule. Thus: Nowhere is this stated. And thus lists of length 2 or longer will never be sorted.
You have two typos in the last clause of the sorted/1 predicate, which should be:
sorted([L1,L2| T]) :- shorter(L1, L2), sorted([L2| T]).

Prolog: Compare 2 Lists and find out if at least one member of the first list exists in the other one

In the quest of learning more about prolog (and in the interest of solving my assignment), I have come across a situation where I need to compare 2 lists and find out if AT LEAST ONE element match ...
Here is an example what I want to do:
?-match([a,b,c],[x,y,z]).
no.
?-match([a,b,c],[x,y,b]).
yes.
My solution up to now:
compare_list([],[]).
compare_list([],_).
compare_list([L1Head|L1Tail],List2):-
member(L1Head,List2),
compare_list(L1Tail,List2).
but this solution gives a true when all the members of List1 are present in List2!
Please people, don't think that I am cheating on an assignment, the problem is much much more complex, I am just stuck at this point and need help to get out of this sticky corner... otherwise I have done the entire assignment myself!
your problem can be solved using the simpler builtins
match(L1,L2) :- member(E,L1),member(E,L2). % full join
add the nasty cut if you are really interested only in 'at least one' solution
match(L1,L2) :- member(E,L1),memberchk(E,L2),!. % really, just the first!
I'll comment on the attempt you've made, which is close, but not quite there:
compare_list([],[]).
compare_list([],_).
The first clause for compare_list/2 says that the empty list has at least one element in the empty list. The second says the empty list has at least one element in any other list. So the first clause is redundant (it's already covered by the second). Whether you want this to be true (that an empty list has an element in any other list) is up to you. Since an empty list has no members, one might consider this a failure case (and, thus, not be declared as true) but you can call it true by definition if you wish. However, it will cause some issues in the recursive case once you have your predicate correctly defined since reducing down to [] will become true and ultimately it might find any list has elements in any list (oops!). I'd leave these two clauses out and consider this case a fail.
compare_list([L1Head|L1Tail], List2):-
member(L1Head, List2),
compare_list(L1Tail, List2).
This says that the first list has an element in the second list if: (1) the head of the list is a member of the second list, AND (2) the tail of the first list has an element in the second list. Does this sound logically correct? If you think this through, given there are no additional compare_list/2 clauses, this is true only if EVERY element of the first list is a member of the second list, as you have observed.
Finally, you're missing the case where the first list has a head that is not a member of the second list. This shouldn't necessarily be a failure since the tail of the first list may have a member in the second list, even if the first element (head) is not a member.
Another way is to use nth0 predicate.
match(L1, L2) :-
nth0(_, L1, SharedItem),
nth0(_, L2, SharedItem).
The first nth0 says "is there a L1 list item with index '_' (ie don't care whether it is in first, second etc. position in the list), whose name is variable SharedItem.
The second nth0 does the same for L2.
But the nice trick is in the unification.. by using the same variable name SharedItem on both nth's, prolog will continue iterating through the lists until the same item is in both.
As always the 'trace.' predicate is your best friend.. run it before calling the above to see what prolog is doing in the background:
[trace] ?- match([a,b,c],[x,y,b]).
Call: (6) match([a, b, c], [x, y, b]) ? creep
Call: (7) lists:nth0(_G1965, [a, b, c], _G1967) ? creep
Exit: (7) lists:nth0(0, [a, b, c], a) ? creep
Call: (7) lists:nth0(_G1968, [x, y, b], a) ? creep
Fail: (7) lists:nth0(_G1968, [x, y, b], a) ? creep
Redo: (7) lists:nth0(_G1968, [a, b, c], _G1970) ? creep
Exit: (7) lists:nth0(1, [a, b, c], b) ? creep
Call: (7) lists:nth0(_G1968, [x, y, b], b) ? creep
Exit: (7) lists:nth0(2, [x, y, b], b) ? creep
Exit: (6) match([a, b, c], [x, y, b]) ? creep
true .
So the 'outer' loop is L1.. it first tries index 0 of L1(a), then when it fails to find it in L2, it does a Redo (of the first nth0), but this time with index 1(b), and finds it, then returns true.
Using your example predicate match/2. The solution is as simple as traverse recursively the List1 (on the left) and check if the Head belongs to the List2 via the memberchk/2 predicate. The reason to use memberchk/2 is that it succeeds only once (i.e., not re-executable on backtracking) and this is what your "AT LEAST ONE" condition states. If the List1 is empty, the predicate fails.
Code:
match([Head|Tail], List2):-
memberchk(Head,List2).
match([_|Tail],List2):-
match(Tail,List2).
Examples:
| ?- match([a,b,c],[x,y,z]).
no
| ?- match([a,b,c],[x,y,b]).
yes
| ?- match([a,b,c],[]).
no
| ?- match([],[x,y,b]).
no

Prolog variable names

for example..
insert(X,Ys,[X|Ys]).
insert(X,[Y|Ys],[Y|Zs]) :- insert(X,Ys,Zs)
why the use of Zs as a variable.. the base case is obviously simple.. head of X::YS.
but the recursive statement is going to be a continuation from the 1st goal.
so for insert(a,[b,c],L) you get L=[a,b,c]
second time around you get [b,a,c]
third time you get [b,c,a]
but what is the actual technical definition of Zs in the program?
[trace] 1 ?- insert(a,[b,c],L).
Call: (6) insert(a, [b, c], _G522) ? creep
Exit: (6) insert(a, [b, c], [a, b, c]) ? creep
L = [a, b, c] ;
Redo: (6) insert(a, [b, c], _G522) ? creep
Call: (7) insert(a, [c], _G595) ? creep
Exit: (7) insert(a, [c], [a, c]) ? creep
Exit: (6) insert(a, [b, c], [b, a, c]) ? creep
L = [b, a, c] ;
Does the continuation begin at the recusive call? Meaning that the 1st goal ended # the base case.. so we start next time # the recursive? Also I can see start using different variable locations for L (aka _G522 vs _G595).
Zs is the result of inserting X into Ys.
In Prolog, you don't usually speak of continuations, but of choice points. When insert(a,[b,c],L) has returned its first result and you start backtracking, the Prolog compiler goes back up into the call chain to find the last choice point:
the last operation was execution of insert's first clause, which was deterministic and bound L;
before that, the last operation was choosing between both clauses, which was a choice point.
Since at this choice point, the first clause was selected, the second one is chosen upon backtracking, causing Zs to be bound in the predicate. L is unbound by backtracking from the first clause and re-bound when the second option returns.
There are no continuations in Prolog, but there's built in backtracking.
To be honest it took me some time too to understand the program.
The thing is that Prolog heavily relies on pattern matching, and choicepoints are inserted when there's more than one pattern that matches. If you want a deterministic program (i.e. without choicepoints) you have to ensure that at a time only one pattern matches (this is the recommended way), or the undesired execution path fails somewhere (this means you throw away all the calculations done in this path). The simplest way to ensure one choicepoint is using the cut operator (!/0).
"what is the actual technical definition of Zs in the program?"
In Prolog you don't have to declare variables, they can be introduced anywhere, and where they get bound (get an actual value, that's immutable) is sometimes hard to follow. Without the first predicate there would be always an unbound variable at the and of the second list, but that variable gets bound when being unified with [X|YS] in the first predicate after the recursive call. As the first predicate doesn't contain a body, the program terminates, and offers a solution to the user. As you see your program can't terminate in the second predicate, only in the first, but that's not surprising from a recursive function, just think of the classic factorial example.
factorial(0,1).
factorial(N,F) :-
N>0,
N1 is N-1,
factorial(N1,F1),
F is N * F1.

Resources