Silly detail enquiry about Prolog unification - list

In Prolog:
?-P=[A|B], P=[1,_].
P = [1, _G1091],
A = 1,
B = [_G1091]
B is shown as [_G1091] showing it's an uninstantiated variable. However, if I change a tiny bit...
?-P=[A|B], P=[1|_].
P = [1,B],
A = 1,
All of a sudden it's not interested in showing me that B is uninstantiated but still a variable ready to unify with anything.. how come? (I like to focus on weird details sometimes :) )

The precise details of Prolog syntax are sometimes quite subtle. To get used to it use write_canonical/1 which shows you the term in functional notation:
?- write_canonical([A|B]).
'.'(_1,_2)
true.
?- write_canonical([1,_]).
'.'(1,'.'(_1,[]))
true.
May I recommend a "drill"-exercise to get used to Prolog's list notation:
Take some list like [[1,2],3] and now try to write it down in as many variants you can imagine.
?- [[1,2],3] == [[1,2],3|[]].
true.
etc.
In many Prologs the toplevel lets you take the last input (often: cursor-up) such that you can re-edit the right-hand side rapidly.

In the first case:
?-P=[A|B], P=[1,_].
you are stating that P is a list with two elements, the first one being the number 1 (unified to variable A). Therefore, B has to be a list with one element (an unnamed variable).
On the other hand, in the second case:
?-P=[A|B], P=[1|_].
you are stating that P is a list with at least one element (1 again unified to A) but you are not stating anything else. B can be either an empty list, or a list with any amount of elements.

If you look at the second part of each query, the first amounts to
P=.(1,.(_,[]))
while the second amounts to
P=.(1,_)
In the first, B is bound to .(_,[]); that is, a list that contains an uninstantiated variable
In the second, B is bound to an uninstantiated variable
When a variable is just bound to an uninstantiated variable, there's no point in showing it; in the first example it's bound to something with some additional structure, so there is a point in showing it.

Related

Checking if the difference between consecutive elements is the same

I am new to using arithmetic in Prolog.
I’ve done a few small programs, but mostly involving logic. I am trying to implement a function that will return true or false if the difference between every consecutive pair of elements is the same or not.
My input would look like this: sameSeqDiffs([3, 5, 7, 9], 2)
I feel like I need to split the first two elements from the list, find their difference, and add the result to a new list. Once all the elements have been processed, check if the elements of the new list are all the same.
I’ve been taught some Prolog with building relationships and querying those, but this doesn’t seem to fit in with Prolog.
Update1: This is what I've come up with so far. I am brand new to this syntax and am still getting an error on my code, but I hope it conveys the general idea of what I'm trying to do.
diff([X,Y|Rest], Result):-
diff([Y,Z|Rest], Result2):-
Result2 = Result,
Z - Y = Result.
Update2: I know I still have much to do on this code, but here is where I will remain until this weekend, I have some other stuff to do. I think I understand the logic of it a bit more, and I think I need to figure out how to run the last line of the function only if there is at least two more things in the rest of the list to process.
diff([X,Y|Rest], Result):-
number(Y),
Y-X=Result,
diff([Rest], Result).
Update3: I believe I have the function the way I want it to. The only quirk I noticed is that when I run and input like: sameSeqDiffs([3,5,7],2).I get true returned immediately followed by a false. Is this the correct operation or am I still missing something?
sameSeqDiffs([X,Y], Result):-
A is Y - X,
A = Result.
sameSeqDiffs([X,Y,Z|T], Result):-
sameSeqDiffs([Y,Z|T], Result).
Update 4: I posted a new question about this....here is the link: Output seems to only test the very last in the list for difference function
Prolog's syntax
The syntax is a bit off: normally a clause has a head like foo(X, Y, Z), then an arrow (:-), followed by a body. That body normally does not contain any arrows :-. So the second arrow :- makes not much sense.
Predicates and unification
Secondly in Prolog predicates have no input or output, a predicate is true or false (well it can also error, or got stuck into an infinite loop, but that is typically behavior we want to avoid). It communicates answers by unifying variables. For example a call sameSeqDiffs([3, 5, 7, 9], X). can succeed by unifying X with 2, and then the predicate - given it is implemented correctly - will return true..
Inductive definitions
In order to design a predicate, on typically first aims to come up with an inductive definition: a definition that consists out of one or more base cases, and one or more "recursive" cases (where the predicate is defined by parts of itself).
For example here we can say:
(base case) For a list of exactly two elements [X, Y], the predicate sameSeqDiffs([X, Y], D) holds, given D is the difference between Y and X.
In Prolog this will look like:
sameSeqDiffs([X, Y], D) :-
___.
(with the ___ to be filled in).
Now for the inductive case we can define a sameSeqDiffs/2 in terms of itself, although not with the same parameters of course. In mathematics, one sometimes defines a function f such that for example f(i) = 2×f(i-1); with for example f(0) = 1 as base. We can in a similar way define an inductive case for sameSeqDiffs/2:
(inductive case) For a list of more than two elements, all elements in the list have the same difference, given the first two elements have a difference D, and in the list of elements except the first element, all elements have that difference D as well.
In Prolog this will look like:
sameSeqDiffs([X, Y, Z|T], D) :-
___,
sameSeqDiffs(___, ___).
Arithmetic in Prolog
A common mistake people who start programming in Prolog make is they think that, like it is common in many programming languages, Prolog add semantics to certain functors.
For example one can think that A - 1 will decrement A. For Prolog this is however just -(A, 1), it is not minus, or anything else, just a functor. As a result Prolog will not evaluate such expressions. So if you write X = A - 1, then X is just X = -(A,1).
Then how can we perform numerical operations? Prolog systems have a predicate is/2, that evaluates the right hand side by attaching semantics to the right hand side. So the is/2 predicate will interpret this (+)/2, (-)/2, etc. functors ((+)/2 as plus, (-)/2 as minus, etc.).
So we can evaluate an expression like:
A = 4, is(X, A - 1).
and then X will be set to 3, not 4-1. Prolog also allows to write the is infix, like:
A = 4, X is A - 1.
Here you will need this to calculate the difference between two elements.
You were very close with your second attempt. It should have been
samediffs( [X, Y | Rest], Result):-
Result is Y - X,
samediffs( [Y | Rest], Result).
And you don't even need "to split the first two elements from the list". This will take care of itself.
How? Simple: calling samediffs( List, D), on the first entry into the predicate, the not yet instantiated D = Result will be instantiated to the calculated difference between the second and the first element in the list by the call Result is Y - X.
On each subsequent entry into the predicate, which is to say, for each subsequent pair of elements X, Y in the list, the call Result is Y - X will calculate the difference for that pair, and will check the numerical equality for it and Result which at this point holds the previously calculated value.
In case they aren't equal, the predicate will fail.
In case they are, the recursion will continue.
The only thing missing is the base case for this recursion:
samediffs( [_], _Result).
samediffs( [], _Result).
In case it was a singleton (or even empty) list all along, this will leave the differences argument _Result uninstantiated. It can be interpreted as a checking predicate, in such a case. There's certainly no unequal differences between elements in a singleton (or even more so, empty) list.
In general, ......
recursion(A, B):- base_case( A, B).
recursion( Thing, NewThing):-
combined( Thing, Shell, Core),
recursion( Core, NewCore),
combined( NewThing, Shell, NewCore).
...... Recursion!

Prolog not showing output in correct format

I am new to Prolog and I am trying to remove the last element from a list. The code I have tried:
removeLast([],[_]).
removeLast([_|T], [_|OT]):-removeLast(T, OT).
Obtained from here. I executed the code from SWi Prolog and I am getting a weird output ...
1 ?-
| removeLast(X, [1,2,3,4]).
X = [_G299, _G302, _G305] .
This is supposed to show [1,2,3], instead it is showing some numbers(?)
I don't know what am I doing wrong, why it is displaying in this format? I tried every Google combination I know of to search this term, although I saw people use this format directly in their queries like, parent(X, _G3248).
Update: Thanks to #lurker, modifying the code to the original format gives the output correctly:
removeLast([],[_]).
removeLast([X|T], [X|OT]):-removeLast(T, OT).
15 ?- removeLast(X, [1,2,3,4]).
X = [1, 2, 3]
But can someone explain, what is _G3240?
Here's the difference in the behavior of the solutions. Let's take the malfunctioning one.
removeLast([],[_]).
This rule says that if I have a list of one element, then the corresponding list with last element removed is [] and I don't care what that one element was (it could even be a variable). This is true, and a valid rule.
removeLast([_|T], [_|OT]) :- removeLast(T, OT).
This rule says that [_|T] is [_|OT] with the last element removed if I don't care what their first elements are and T is OT with its last element removed (following the same rules). This doesn't sound quite right. It means that if I am removing the last element from a list, I don't care what element I have in my result. So you get an arbitrary list of elements whose count is one less than your original list. But the elements don't match those at the front of the original list. In Prolog, the two _ instances are different anonymous variables. They are not unified.
The corrected clause is:
removeLast([X|T], [X|OT]) :- removeLast(T, OT).
This says that a list [X|T] is the list [X|OT] with its last element removed if T is the list OT with its last element removed. The common X means they share the same head of the list, which is correct. When the recursion reaches the very last element of the second argument, then the first clause is matched and that single-element tail is replaced by the empty list []. And then you get the correct, final result.
I refer to the _ variable as "anonymous" rather than "don't care" since there are some uses for anonymous variables in which their values do matter. Often though, as in this case, they are used when the value is not being used.

Declarative interpretation of this program that says if an element belongs to a list

From what I have understood the declarative paradigm indicate what is important to reach the solution and not how reach it but, being accustomed to think procedurally, I often make confusion...
So the solution is this one:
mymember(X, [X|_]).
mymember(X,[_|T]) :- mymember(X,T).
This is my declarative interpretation of this simple program:
1) X belong to the list if it is TRUE that X is the Head of this list (if the head element of the list unifies with the X element that I would know if is in the list)
2) If the first fact is not true (X don't unifies with the first list element) the program try to execute the second rule (and maybe here I have some interpretation problem). This rule say that: the head is true if the body of the rule is true)
The head of rule say that: X belongs to the TAIL of the list (I use an anonymous variable using the _ character to say that don't care of the first element of the list)
So this rule say that: It is TRUE that the X element belong to list without its head if it is TRUE that the X element belong to the tail of the list
Is it a correct declarative and logic interpretation of this program or I am missing something?
You're reading them as exclusive-or, but they're actually inclusive-or. Both 1) and 2) are correct, minus the connective "if the first fact is not true". It's not necessary for 1) to be false for 2) to hold. In other words, it can be true that X is both the head of the list and present in the tail of the list (for instance mymember(a, [a, b, a]).
Edit: responding to your comment.
There's a language barrier issue here, so let me try answering your question with yes and no.
Yes, that using ; produces another answer is evidence that Prolog was able to compute alternative answers. In one sense, ; triggers backtracking manually, but in another sense it is Prolog asking you if this is the answer you wanted, and then you're able to say "yes" or "no." When you say ; you're telling Prolog, in essence, "this isn't the right answer." But this is not the only way to trigger backtracking; in fact, most of the time you won't trigger it manually at all.
For instance, let's look at this:
even_member(X, L) :- member(X, L), 0 is X mod 2.
?- even_member(X, [1,5,17,23,4,19]).
X = 4 ;
false.
So here I defined a predicate that says, declaratively, X is an even_member of L if X is a member of L and X mod 2 = 0. When I used the predicate, we got the answer X = 4. We then pressed ; to say, this isn't the right answer, and Prolog said there are no more answers. But internally, member(X, L) backtracked 5 times before it found an element that satisfied the second part of the predicate--in other words, the statement 0 is X mod 2 tells Prolog that 1, 5, 17 and 23 are "wrong" the same way we do by pressing ; interactively. When we said we wanted another answer, we engaged the same machinery, so Prolog went back to member(X, L), found 19, and then found that 19 is not divisible by two and gave up.
Prolog backtracked six times, five of those times just to get the one answer. We only asked it to backtrack once, and it happened that it was the last possibility so it didn't backtrack again.
Let me try:
mymember(X, [X|_]).
X is a member of the list if it's the first element of the list
mymember(X,[_|T]) :- mymember(X,T).
X is a member of the list if it's a member of the rest of the list.
Suppose I give you a stack of (paper) programmer resumes and say "see if there is a programmer who knows Prolog among these"
What do you do? You look at the top resume. If that programmer knows Prolog, you're done.
If not, then the only way there can be such a resume is if it's in the rest of the stack.
point 2) doesn't hold: Prolog will try each rule searching for a solution.
But it will follow a strictly specified order searching in your database, resulting in a depth first search of the solution space.
I would read
X is a member of a list if it is the first element (i.e. unify the head, clause 1), or is a member of the tail (clause 2).

Prolog: take a list of two elements, return true if and only if the first element is same as second

I'm a newbie prolog programmer, and for an assignment, I have to have a basic program that succeeds if and only if list X is a list of two elements, with the first as the same as the second.
From my view of prolog, programs seem to be pretty small, so I typed this in:
firstPair(x,x).
When I run it under swipl, I get this as output:
Syntax error: Operator expected
Is there something more that needs to be done? I thought that if I executed this with say, firstPair(1,2). this would be all it would need to know that it is false.
First, lowercase x is not a variable, it's an atom. Make x uppercase to fix the problem:
firstPair(X,X).
Second, you do not type this into the interpreter. Rather, you write it into a file firstPair.pl, and then read that file into Prolog.
At the command prompt, type this:
['firstPair.pl'].
Press enter. Now you can use your firstPair/2 rule.
Finally, since the assignment talks about lists, I think the instructor wanted you to write firstPair/1, not firstPair/2:
firstPair([X,X]).
Your program/fact
firstPair(X,X).
will succeed if the two arguments given it can be unified, whether they are lists, atoms, variables, etc. To meet your specification, a
program that succeeds if and only if list X is a list of two elements,
with the first as the same as the second.
You need something like this:
list_of_two_elements( [X,X] ).
This will succeed if passed a single term that is (or can be unified with) a list of two elements that are, or can be made through unification, identical. For instance, all of the following will succeed:
list_of_two_elements( X ).
on success, the variable X will be unified with a list of two elements containing the same unbound variable, something like [V1,V1].
list_of_two_elements( [1,1] ).
list_of-two_elements( [1,X] ). (on success, X here will have been unified with the integer 1.)

Prolog: Difference of two lists

Pretty new to Prolog. I'm trying to give two lists and have the difference of the two returned to me. The second list can have bound variables and unbound variables in it. I've tried tracing this and it recurses all the way through and gives me a correct list in NewL, but then on the way back it negates all the deletes I've made. What is going wrong ? Thanks for the help!
% Find difference between two lists, return result in Difference
difference(List,[H|T],Difference) :- % When H is unbound var, use Tail
var(H),!,difference(List,T,Difference),!.
difference(List,[H|T],Difference) :- % When H is bound var, remove from List.
subtract(List,[H],NewL),
difference(NewL,T,Difference),!.
Assuming that subtract/3 comes from SWI-Prolog library, and thus is correct, you are left with just one possibility: you forgot to declare the base case on the second argument, that drives the recursion.
And take in account the comment from #mog, cuts should be used just when required. Of course, to decide when are required can be difficult...