Adventure In Prolog: Why does ?- gizmo(X,X). fail? - prolog

I'm new to Prolog and working through the exercises for Chapter 3 of Adventure In Prolog. Given the logicbase:
gizmo(a,1).
gizmo(b,3).
gizmo(a,2).
gizmo(d,5).
gizmo(c,3).
gizmo(a,3).
gizmo(c,4).
Why is it that
| ?- gizmo(X,X).
results in the following trace?
More specifically, why does it fail?
| ?- gizmo(X,X).
1 1 Call: gizmo(_279,_279) ? c
1 1 Fail: gizmo(_279,_279) ? c
(1 ms) no
{trace}
Since
gizmo(a,X)
and
gizmo (X,3)
,for example, both seem to act like wildcards and return every possible a and every possible 3 result respectively...
I thought that
gizmo(X,X)
would return every possible result for both sides (both the letters and numbers) but instead returns a fail, and no other result.
Would someone be willing to explain why it's a fail instead of returning all values from each side, keeping in mind I am a beginner?
Thanks in advance.

X is a variable but it's a unique one. gizmo(X,X). will return every possible value of X for which it is true. But that's the same value on the left and right side because it's the same variable (namely, X).
If you had a fact gizmo(z,z)., then gizmo(X,X). would correctly return X = z.
To get every possible pairs for which gizmo is true, you want to use gizmo(X,Y). or any other variables names as long as they are different.

Related

Prolog: what is difference between, for example, X is 3 and 3 is X?

three(X) :- 3 is X.
three2(X) :- X is 3.
Requests three(3), three(5) and three2(3), three2(5) respectively have the same answers.
But three2(X) has answer 3, while three(X) has answer "Arguments are not sufficiently instantiated".
If there's enough data to solve that three(3) is true and three(5) is false, why there's not enough data to find that X is equals 3 when we request for the value of X?
That's because is/2 is the numeric expression evaluator of Prolog. Everything on the Right Hand Side of is/2 must be fully instantiated so that the expression can then be evaluated to a number (possibility missed: evaluate to something else than numbers). The result is then unified with the Left Hand Side of is/2. This succeeds if the LHS is an unbound variable or the same as the result obtained.
In your case, you can make the predicate three/1 symmetric by just unifying, as there is really nothing to evaluate:
three_sym(X) :- 3 = X.
Succeeds with 3 and outputs the answer X = 3 for an unbound X.

Prolog, Dynamic Programming, Fibonacci series

I should preface this by saying this is a homework problem that I am having issues with, and Im not sure if that sort of thing is allowed around here, but I dont know where else to turn to. This is the question I've been asked:
In the sample code for this question, you can see a Fibonacci predicate fibSimple/2 which calculates the Fibonacci of X, a natural number. The problem with the naive recursive solution, is that you end up recalculating the same recursive case several times. See here for an explanation.
For example, working out the fib(5) involves working out the solution for fib(2) three separate times. A Dynamic Programming approach can solve this problem. Essentially, it boils down to starting with fib(2), then calculating fib(3), then fib(4) etc.... until you reach fib(X). You can store these answers in a list, with fib(X) ending up as the first item in the list.
Your base cases would look like the following:
fib(0,[0]).
fib(1,[1,0]).
Note the way that fib(1) is defined as [1,0]. fib(1) is really 1 but we are keeping a list of previous answers.
Why do we do this? Because to calculate fib(X), we just have to calculate fib(X-1) and add the first two elements together and insert them at the front of the list. For example, from the above, it is easy to calculate fib(2,Ans). fib(2) in this case would be [1,1,0]. Then fib(3) would be [2,1,1,0], fib(4) would be [3,2,1,1,0] etc....
Complete the fib/2 predicate as outlined above - the base cases are shown above. You need to figure out the one line that goes after the base cases to handle the recursion.
This is the sample code they provided
fibSimple(0,0). % fib of 0 is 0
fibSimple(1,1). % fib of 1 is 1
fibSimple(N,X) :- N>1,fibSimple(N-1,A), fibSimple(N-2,B), X is A+B.
fib(0,[0]).
fib(1,[1,0]).
I've had a few attempts at this, and while I'm fairly certain my attempt will end up being hopelessly wrong, this is what I have most recently tried
fib(X,[fib(X-2)+fib(X-1) | _]).
My reasoning to this is that if you can get the answer to the last 2, and add them together making them the first or "head" of the list, and then the underscore representing the rest.
My 2 issues are:
1) I don't know/think this underscore will do what I want it to do, and am lost in where to go from here
and
2) I don't know how to even run this program as the fib\2 predicate requires 2 parameters. And lets say for example I wanted to run fib\2 to find the fibonacci of 5, I would not know what to put as the 2nd parameter.
Because this is homework I will only sketch the solution - but it should answer the questions you asked.
A predicate differs from a function in that it has no return value. Prolog just tells you if it can derive it (*). So if you just ask if fib(5) is true the best you can get is "yes". But what are the Fibonacci numbers from 1 to 5 then? That's where the second argument comes in. Either you already know and check:
?- fib(5, [5, 3, 2, 1, 1, 0]).
true ; <--- Prolog can derive this fact. With ; I see more solutions.
false <--- no, there are no other solutions
Or you leave the second argument as a variable and Prolog will tell you what values that variable must have such that it can derive your query:
?- fib(5, X).
X = [5, 3, 2, 1, 1, 0] ;
false.
So the second argument contains the result you are looking for.
You can also ask the other queries like fib(X,Y) "which numbers and their fibonacci hostories can we derive?" or fib(X, [3 | _]) "which number computes the the fibonacci number 3?". In the second case, we used the underscore to say that the rest of the list does not matter. (2)
So what do we do with fib(X,[fib(X-2)+fib(X-1) | _]).? If we add it to the clauses for 0 and 1 you were given we can just query all results:
?- fib(X,Y).
X = 0,
Y = [1] ; <-- first solution X = 0, Y = [1]
X = 1,
Y = [1, 0] ; <-- second solution X = 1, Y = [1, 0]
Y = [fib(X-2)+fib(X-1)|_2088]. <-- third solution
The third solution just says: a list that begins with the term fib(X-2)+fib(X-1) is a valid solution (the _2088 as just a variable that was not named by you). But as mentioned in the beginning, this term is not evaluated. You would get similar results by defining fib(X, [quetzovercaotl(X-1) | _]).
So similar to fibSimple you need a rule that tells Prolog how to derive new facts from facts it already knows. I have reformatted fibSimple for you:
fibSimple(N,X) :-
N>1,
fibSimple(N-1,A),
fibSimple(N-2,B),
X is A+B.
This says if N > 1 and we can derive fibSimple(N-1,A) and we can derive fibSimple(N-2,B) and we can set X to the result of A + B, then we derive fibSimple(N, X). The difference to what you wrote is that fibSimple(N-1,A) occurs in the body of the rule. Again the argument N-1 does not get evaluated. What actually happens is that the recursion constructs the terms 3-1 and (3-1)-1) when called with the query fib(3,X). The actual evaluation happens in the arithmetic predicates is and <. For example, the recursive predicate stops when it tries to evaluate (3-1)-1 > 1 because 1>1 is not true. But we also do not hit the base case fibSimple(1, 1) because the term (3-1)-1 is not the same as 1 even though they evaluate to the same number.
This is the reason why Prolog does not find the Fibonacci number of 3 in the simple implementation:
?- fibSimple(3, X).
false.
The arithmetic evaluation is done by the is predicate: the query X is (3-1) -1 has exactly the solution X = 1. (3)
So fibSimple must actually look like this: (4)
fibSimple(0,1).
fibSimple(1,1).
fibSimple(N,X) :-
N>1,
M1 is N -1, % evaluate N - 1
M2 is N -2, % evaluate N - 2
fibSimple(M1,A),
fibSimple(M2,B),
X is A+B.
For fib you can use this as a template where you only need one recursive call because both A and B are in the history list. Be careful with the head of your clause: if X is the new value it can not also be the new history list. For example, the head could have the form fib(N, [X | Oldhistory]).
Good luck with the homework!
(1) This is a little simplified - Prolog will usually give you an answer substitution that tells you what values the variables in your query have. There are also some limited ways to deal with non-derivability but you don't need that here.
(2) If you use the arithmetic predicates is and > these two queries will not work with the straightforward implementation. The more declarative way of dealing with this is arithmetic constraints.
(3) For this evaluation to work, the right hand side of is may not contain variables. This is where you would need the arithmetic constraints from (2).
(4) Alternatively, the base cases could evaluate the arithmetic terms that were passed down:
fibSimple(X, 0) :-
0 is X.
fibSimple(X, 1) :-
1 is X.
fibSimple(N,X) :-
N>1,
fibSimple(N-1,A),
fibSimple(N-2,B),
X is A+B.
But this is less efficient because a single number takes much less space than the term 100000 - 1 - 1 -1 .... -1.

Prolog: Counting occurrences of an element in a list returning multiple answers

I'm having a bit of trouble with something. I've wrote a function that returns the number of occurrences of an element in a list. Here is the code:
occurencesHelp(X,[],N,N).
occurencesHelp(X,[X|T],N,Y) :-
N1 is N+1,
occurencesHelp(X,T,N1,Y).
occurencesHelp(X,[H|T],N,Y) :-
occurencesHelp(X,T,N,Y).
occurences(X,List,N) :-
occurencesHelp(X,List,0,N).
This works fine, the first answer I get is:
N = 5 ?
but then there are multiple answers such as:
N = 4 ? ;
N = 4 ? ;
N = 3 ? ;
N = 4 ? ;
N = 3 ? ;
and so on. I've tried tracing through to see if I can see why this is the case but can't figure it out. I think using a cut would help me, but we have been specifically told not to use cut, so that isn't an option. Any help would be appreciated.
Thanks.
When I load your code in SWI-Prolog, I get the following warnings:
Warning: /home/isabelle/occ.pl:1:
Singleton variables: [X]
Warning: /home/isabelle/occ.pl:7:
Singleton variables: [H]
These warnings are important. Singleton variables are very often a sign that you have made a serious logical error. In your case, let's look at line 7. It's in this clause:
occurencesHelp(X,[H|T],N,Y) :-
occurencesHelp(X,T,N,Y).
Prolog tells us that H is a singleton variable. This means that it only occurs once in this clause, and this means that we forgot to put H in a relation with the other variables.
The previous clause says (procedurally): "if the head of the list is X, increment the counter". Conversely, this clause should say: "if the head of the list is not X, keep the counter unchanged". But it does not say that about the head of the list: In fact, it doesn't say anything about H (hence the warning).
So what you need to add is a goal expressing the fact that X and H should be unequal. Two ways to express this are X \= H and dif(X, H). In your case, the choice depends on what you have already learned in your course.
(The singleton warning for line 1 is benign in this case; you can just replace X by _X to tell Prolog that you explicitly want to ignore that variable.)

How Prolog's logical update view works for assert and retract?

Can someone please explain the Prolog logical view about assert and retract in details?
For example in code below, in the first run Prolog returns true and in subsequent runs returns false. I don't know why because of Prolog logical view when asserta(nextBound(100)) satisfies, nice(X) is still frozen with values when it started so this change should be ignore and nextbound(100) must be false.
nextBound(10000).
nice(X) :-
asserta(nextBound(100)),
retract(nextBound(10000)),
nextBound(100).
You can do a trace to determine what happens:
| ?- nice(_).
1 1 Call: nice(_17) ?
2 2 Call: asserta(nextBound(100)) ?
2 2 Exit: asserta(nextBound(100)) ? <-- 1st assert of netBound(100) succeeds
3 2 Call: retract(nextBound(10000)) ?
3 2 Exit: retract(nextBound(10000)) ? <-- retract nextBound(10000) succeeds
4 2 Call: nextBound(100) ?
4 2 Exit: nextBound(100) ? <-- Succeeds because netBound(100) now a fact
1 1 Exit: nice(_17) ?
(1 ms) yes
{trace}
| ?- nice(_).
1 1 Call: nice(_17) ?
2 2 Call: asserta(nextBound(100)) ?
2 2 Exit: asserta(nextBound(100)) ? <-- 2nd assert of netBound(100) succeeds
3 2 Call: retract(nextBound(10000)) ?
3 2 Fail: retract(nextBound(10000)) ? <-- retract nextBound(10000) fails
1 1 Fail: nice(_17) ?
(3 ms) no
{trace}
| ?-
You can see that, in the first case, first the nextBound(100) fact is successfully asserted (for the 1st time). Then, the retract(nextBound(10000)) succeeds because nextBound(10000). is a fact which exists in the data. Following that, the query nextBound(100) succeeds because two steps before this fact was asserted into the data.
On the second execution of nice(_), nextBound(10000) doesn't exist because it was retracted in the first execution, and the code doesn't re-assert it. So, in the second execution of nice(_), retract(nextBound(10000)) fails because the fact nextBound(10000) doesn't exist and the entire second execution of nice(_) fails at that point since backtracking over asserta and retract do not re-execute and produce additional results.
A listing shows that now there are two nextBound(100) facts, since we've asserted one in each of the two runs of nice(_), and no nextBound(10000) since it was retracted in the first run of nice(_):
| ?- listing.
% file: user
nice(_) :-
asserta(nextBound(100)),
retract(nextBound(10000)),
nextBound(100).
% file: user_input
nextBound(100).
nextBound(100).
(1 ms) yes
| ?-
The logical update view, as stated in the SWI documentation, says, Starting with SWI-Prolog 3.3.0 we adhere to the logical update view, where backtrackable predicates that enter the definition of a predicate will not see any changes (either caused by assert/1 or retract/1) to the predicate.
In other words, the logical update view prevents the predicate from dynamically changing itself while it's executing. That's not the scenario here.
In fact, it's critical in Prolog that, during the execution of a predicate, if you assert a fact at one point in the predicate, that result must be visible in it immediately, or the predicate may not be able to function properly. There are many many common library predicates that rely on this behavior.
To start from a historical view, the logical update view has been first implemented in Quintus 2.0 (whose current successor is SICStus) and described in the literature in 1987. It has been adopted in ISO Prolog ISO/IEC 13211-1:1995. The principal idea is that any goal of a dynamic predicate will take exactly those clauses into account that are present at the point in time when the goal is executed. Any further changes — be they additions or deletions — are not taken into account for the execution of that very goal.
Prior to the logical update view, there have been various more or less consistent implementations, most were incompatible with various optimizations for Prolog systems. Note that the difference only shows if you have goals that may have more than one answer. Either as a simple goal, or when using retract and you are using retract/1 or assertz/1. The difference does not show when using asserta/1 only. So your example cannot clarify the differences.
Consider a dynamic predicate p/1. Since the following interaction is using the toplevel only, I will make p/1 known to the system by asserting a fact and immediately retracting all facts of p/1. Also, I will remove all facts with retractall(p(_)) before starting the next query.
?- asserta(p(1)).
true. % now p/1 is known to the system.
?- retractall(p(_)), assertz(p(1)), p(X), assertz(p(2)).
X = 1. % only one answer!
?- retractall(p(_)), assertz(p(1)), p(X), assertz(p(2)), p(Y).
X = 1, Y = X
; X = 1, Y = 2.
So the first goal p(X) sees only p(1), whereas the second goal p(Y) sees both. This applies for any active goal:
?- retractall(p(_)), assertz(p(1)), assertz(p(2)), p(X), assertz(p(3)), p(Y).
X = 1, Y = X
; X = 1, Y = 2
; X = 1, Y = 3
; X = 2, Y = 1
; X = 2, Y = X
; X = 2, Y = 3
; X = 2, Y = 3
; false.
Again, note that X is only 1 or 2 but not 3.
Alternatively, you can imagine that each goal p(X) is replaced by:
... findall(Xi, p(Xi), Xis), member(X, Xis) ...
This shows you a bit the idea behind: Conceptually, all answers are stored temporally, and only then each answer is shown.
Er, above is not quite true, for only the clauses of p/1 are handled this way. That is, as long as you are storing only facts, above explanation is perfect, but should you also store rules, you would need a more complex explanation, roughly:
... findall(Xi-Bi, clause(p(Xi),Bi), XiBis), member(X-B,XiBis), B ...
And, again, this is not the plain truth, for some more exotic issues like cuts might intervene. I will leave it that way for the moment1.
Similarly, retract/1 will also see and delete the clauses it sees at the point in time of executing it. For most situations this is quite intuitive and agrees with our expectations. Nevertheless, there are quite absurd situations as the following:
?- retractall(p(_)),
assertz(p(1)), assertz(p(2)),
retract(p(X)), ( X = 1, retract(p(Y)) ; X = 2, Y = none ).
X = 1, Y = 2
; X = 2, Y = none.
Here, the fact p(2) was deleted twice, although the data base contained only a single fact p(2).
Footnotes
1 Actually, replace
... p(X) ...
by
... findall(Xi-Bi, clause(p(Xi),Bi), XiBis), answs_goal_x(XiBis,X, G), G ...
with
answs_goal_x([], _, true).
answs_goal_x([Xi-Bi|XiBis], X, ( X = Xi, Bi ; G) ) :-
answs_goal_x(XiBis, X, G).

index of element

I'm new to s.o and new to Prolog which is what i am working on, specifically SWI-Prolog.
I am trying to do as the title says, and have gotten it to work on a 1 based list (starting at 1 instead of zero) using some methods that were included in the SWI-library.
and this is my code:
indexof(I,E,L):-
nth1(I,L,E).
indexof(-1,_,_).
My assignment (yes it's hw -_-) is to do this but as a 0 based count
i tried on the last line to add I is I - 1 but i kept getting errors. Is there any other way to get it into a 0 based count?
so for this indexof(A,a,[w,x,y,z,a]). i should get 4 but am getting 5.
SWI-Prolog has nth0/3 which is just like nth1/3 but the index starts at 0.
To make your original approach work, you need something like:
indexof(I,E,L) :-
nth1(I1,L,E),
I is I1 - 1.
Prolog variables can only be assigned once. If you tried I is I - 1, you're claiming that I is itself minus 1. That's never true, so the predicate fails. You need to use an intermediate variable, like I1 in the example above.
The definition of nth1/3 is nth1(?Index, ?List, ?Elem). The ? means that the argument doesn't have to be instantiated, so Prolog will fill it for you, and that means you don't even have to make a new predicate for the purpose! Here's an example for using the built-in nth1/3 predicate this way:
?- nth1(I, [1,2,3,1,3,4,5], 1).
I = 1 ;
I = 4 ;
false.
?- nth1(I, [1,2,3,1,3,4,5], 2).
I = 2 ;
false.
?- nth1(I, [1,2,3,1,3,4,5], 3).
I = 3 ;
I = 5 ;
false.

Resources