Related
In predicate logic, why does P(x) and P(f(x)) have no unifiers? One of my solutions is replacing x with f(x), but I'm not sure why I am wrong.
Let's see what happens if you replace x with f(x):
P(x) becomes P(f(x))
P(f(x)) becomes P(f(f(x)))
And the result isn't the same; so it's not a unifier.
In general when the difference term involves itself as in this case (i.e., x differing from f(x)) you cannot unify them since whatever you substitute for x would change both terms in an unequal way, assuming they are not equal to start with.
Another way to think about this the so called occurs-check. Since x occurs in f(x) you cannot unify these two terms. You can read about the occurs-check here: https://en.wikipedia.org/wiki/Occurs_check
I would expect that the following should always be true if a comparison backtrack, right? unless it goes into an infinite loop!
?- Y=2 , random:random(1,3,X), X =\= Y.
Y = 2,
X = 1.
?- Y=2 , random:random(1,3,X), X =\= Y.
false.
but I got false!
In general, my question is why doesn't comparison backtrack?
Thanks for all the answers. My confusion seemed to come primarily from my expectation of random keep generating new-random numbers, so I confused that comparison was not backtracking, instead, the reason was that random does its thing only once and fails afterwards.
I was unaware of semi-determinate nature of some predicates.
But now I can be on a lookout ;) for cases like this. thanks again.
In your example, there is nothing to backtrack.
All predicates you are using in these examples ((=)/2, random/3 and (=\=)/2) are semi-deterministic: This means that they either fail, or succeed exactly once.
In other words, they can all succeed at most once.
Therefore, if at least one of these predicates fails, then the query fails.
To generate a succession of pseudo-random numbers on backtracking, use for example repeat/0.
Warning: random/3 is an impure predicate: It may yield different solutions even though the query is exactly the same. It may lead to failure on one invocation, and to success on another. This complicates testing and reasoning about your code considerably.
Prolog works with what are called Horn-clauses. This means that each term individually, for example Y=2, is a separate goal in a question to be answered. The result will be yes or no for each goal, and if all goals answer yes, the question is answered with yes.
What your code asks is as follows:
%Is Y equal to 2 or can it be made equal?
%Yes, Y is a variable and can be assigned the numerical atom 2
Y=2 ,
%Give me a random number between 1 and 3.
%Is X equal to the random number or can it be made equal?
%Yes, X is a variable and can be assigned the outcome atom of random:random
random:random(1,3,X),
%is the term contained within X NOT equivalent to Y?
X =\= Y.
You can check out existing comparison predicates in for example the SWI documentation or on Learn Prolog Now!.
Depending on your implementation you can use trace and write to output the actual atoms in the variables, allowing you to explore how your program actually works.
?- trace, (Y=2 , random:random(1,3,X), write(X),nl, X =\= Y). %SWI-Prolog
SWI-prolog online editor
Infinite recursion looks like p(P) :- p(P).. It has a call to the question it is supposed to solve inside the answer itself, meaning to solve for p(P) it will check p(P), which never ends.
Backtracking only happens when Prolog has choicepoints. Choicepoints are points where in the decision tree, there are MULTIPLE POSSIBLE WAYS to satisfy the question Prolog is currently processing. Prolog works from top to bottom, then left to right.
Think of a cars salesman who gets asked "which car is the best for me?". He has more than one possible car to sell you, so he'll start showing you different cars that meet your criteria. The car needs to have a transport capacity of a volume over 400 liters? All cars that don't satisfy this condition are not presented as a solution.
Prolog does a depth-first search, meaning it goes down to the first answer it finds, then checks whether there's other ways to answer it. If there is no result, the answer is no. If there is at least one solution, the answer is yes and you get all possible answers for your question. This way you only get results that satisfy a whole chain of goals you've set.
I think this will help.
% Generate random value from Min to Max(with backtrack)
rand_backtrack(Min,Max,RandVal):-
create_list(Min,Max,List),
randomize_list(List,Randomized),
length(Randomized,Len),
% Choose one Variable from Randomized (From first element to last).
% When backtrack occured, next element is chosen.
between(1,Len,Idx),
nth1(Idx,Randomized,RandVal).
% create integer order list
% [Min,Min+1,Min+2,....,Max]
create_list(Max,Max,[Max]):-!.
create_list(Min,Max,[Min|Rest]):-
Min1 is Min+1,
create_list(Min1,Max,Rest).
% shuffle List.
% result always changes.
% ex.randomize_list([1,2,3,4,5,6],R) R=[4,2,6,1,3,5]
%
randomize_list([Val],[Val]):-!.
randomize_list(List,[RandVal|RestRandomized]):-
length(List,Len),
random(1,Len,RandIdx),
nth1(RandIdx,List,RandVal),
select(RandVal, List, Rest),
!,
randomize_list(Rest,RestRandomized).
?- rand_backtrack(3,19,A).
A = 6 ;
A = 4 ;
A = 8 ;
A = 13 ;
A = 15 ;
A = 16 ;
A = 9 ;
A = 18 ;
A = 7 ;
A = 3 ;
A = 12 ;
A = 10 ;
A = 17 ;
A = 11 ;
A = 14 ;
A = 5 ;
A = 19.
I am writing a rule that is looking for a particular integer. I assumed I can write something like this
find_number(X):-
integer(X),
X > 1, X < 5.
Then expect the result of a query to integer(X) to result in X=2, X=3, X=4, false. Instead, I just get a false result. The only way I found to write this rule is to use numlist/3 like so
find_number(X):-
numlist(2, 4, NumList),
member(X, NumList).
Can anyone explain why this is?
Your reasoning would be perfectly valid iff integer/1 were an actual relation that satisfies basic logical properties.
For example, in classical logic, a unary predicate P satisfies the following property:
If P(σ(T)) is satisfiable for any substitution σ and term T, then P(T) is also satisfiable.
This seems completely obvious and of course holds also for all pure predicates in Prolog.
The problem is that integer/1 is not a pure relation.
In particular, we have for example:
?- integer(3).
true.
Yet the following more general query fails:
?- integer(X).
false.
Is there any integer? No.
Believe it or not, that's how integer/1 actually works.
Clearly, something seems not quite right for such predicates, and so there are better alternatives in all widely used modern Prolog systems. I strongly recommend you use such alternatives instead, to get the most out of Prolog.
For the case of integers, I recommend you check out CLP(FD) constraints (clpfd).
For example, in GNU Prolog, your code could look like this:
good_number(X) :-
X #> 1,
X #< 5.
With the following queries and answers:
| ?- good_number(X).
X = _#2(2..4)
| ?- good_number(X), fd_labeling([X]).
X = 2 ? ;
X = 3 ? ;
X = 4
This works exactly as we expect a relation to work! I have taken the liberty to change the name such that it makes sense also in more specific cases, where there is nothing left to "find":
| ?- good_number(3).
yes
Depending on your Prolog system, you may have to import a library to use such more declarative features. See also logical-purity for more information.
You get only false because integer/1 tests if the input is an integer and if it is it succeeds else if it is not an integer or if it is a variable that is not instantiated as in your case, then it fails.
You could use between/2 built in predicate:
find_number(X):-between(2,4,X).
This will return:
?- find_number(X).
X = 2 ;
X = 3 ;
X = 4.
I have the following Prolog Program:
p(f(X), Y) :- p(g(X), g(Y)).
p(g(X), Y) :- p(f(Y), f(X)).
p(f(a), g(b)).
The prolog proof tree has to be drawn for the predicate p(X, Y).
Question:
Why is Y matched to Y1/Y and not to Y/Y1 and why is Y used further on?
if I match a predicate (e.g. p(X, Y)), I get a new predicate (e.g. p(g(X1), g(Y))) - why contains p(g(X1), g(Y)) just one subtree? I mean, shouldn't it have 3 because the knowledgebase contains 3 statements - instead of just 1?
And why is at each layer of the tree matched with something like X2/X1 and so on ? and not with the predicate before ?
Shouldn't it be g(X1)/fX5, g(Y1)/Y5 ?
Note: Maybe it seems that I have never done a tutorial or something. But I did.. I appreciate every help.
To be honest, I have rarely seen a worse method to explain Prolog than what you show here.
Yes, I expect the author meant Y/Y1 instead of Y1/Y in both cases, otherwise the notation would be quite inconsistent.
As to your other questions: You are facing the usual problems that arise when taking such an extremely operational view of Prolog. The core issue is that this method doesn't scale: You do not have the mental capacity to carry this approach through. Don't take this personal: Humans in general are bad at keeping all details of an execution tree that grows exponentially in mind. This makes the whole approach extremely cumbersome and error-prone. For comparison, consider why human grandmasters have stopped competing against chess computers already many years ago. In this concrete case, note for example that the rightmost branch does not even arise in actual Prolog execution, but the graph wrongly suggests that it does!
Part of the problem here is a confusion in terminology: Please note that Prolog uses unification (not "matching", which is one-sided unification). When you unify a goal with a clause head and the unification succeeds, then you get bindings for variables. You continue with these bindings in place.
To make the whole approach remotely feasible, consider fragments of your program.
For example, suppose I only give you the following fact:
p(f(a), g(b)).
And you then query:
?- p(X, Y).
X = f(a),
Y = g(b).
This answers shows the bindings for X and Y. First make sure you understand this, and understand the difference between these bindings and a "new predicate" (which does not arise!).
Also, there are no "statements", but 3 clauses, which are logical alternatives.
Now, again to simplify the whole task, consider the following fragment of your program, in which I only look at the two rules:
p(f(X), Y) :- p(g(X), g(Y)).
p(g(X), Y) :- p(f(Y), f(X)).
Already with this program, we get:
?- p(X, Y).
nontermination
Adding a further pure clause cannot prevent this nontermination. Thus, I recommend you start with this reduced version of your program, and consider it in more depth.
From there, you can add the remaining fact again, and consider the differences.
Very good questions!
Why is Y matched to Y1/Y and not to Y/Y1 and why is Y used further on?
The naming here seems a little arbitrary in that they could have used Y/Y1 but then would need to use Y1 further on. In this case, they chose Y1/Y and use Y further on. Although the author of this expression tree was inconsistent in their convention, I wouldn't be too concerned about the naming as much as whether they follow the variable correctly down the tree.
if I match a predicate (e.g. p(X, Y)), I get a new predicate (e.g. p(g(X1), g(Y))) - why contains p(g(X1), g(Y)) just one subtree? I mean, should'nt it have 3 because the knowledgebase contains 3 statements - instead of just 1?
First a word on term versus predicate. A term is only a predicate in the context of Head :- Body in which case Head is a term that forms the head of a predicate clause. If a term is an argument to a predicate (for example, p(g(X1), g(Y)), the g(X1) and g(Y) are not predicates. They are just terms.
More specifically in this case, the term p(g(X1), g(Y)) only has one subtree because it only matches the head of one of the 3 predicate clauses which is the one with the head p(g(X), Y) (it matches with X = X1 and Y = g(Y)). The other two can't match since they're of the form p(f(...), ...) and the f(...) term cannot match the g(X1) term.
And why is at each layer of the tree matched with something like X2/X1 and so on ? and not with the predicate before ?
Shouldn't it be g(X1)/fX5, g(Y1)/Y5 ?
I'm not sure I'm following this question, but the principle to follow is that the tree is attempting to use the same variable name if it applies to the same variable in memory, whereas a different variable name (e.g., X1 versus X) is used if it's a different X. For example, if I have foo(X, Y) :- <some code>, bar(f(X), Y). and I have bar(X, Y) :- blah(X), ... then the X referred to in the bar predicate is different than the X referred to in the foo predicate. So we might say, in the call to foo(X, Y) we're calling bar(f(X), Y), or alternatively, bar(X1, Y) where X1 = f(X).
In the query below, firstly I'm getting X = H128, where does that come from? Also why is it returning yes? Is it because the variable X is actually not defined and we are testing for that condition?
?- not(X==3).
X = H128
yes
Your query is using an uninstantiated variable (X).
When checking whether X is instantiated with the term 3 it (X==3) it fails because X is uninstantiated.
Therefore, not(X==3) will succeed as the prolog engine cannot prove X==3.
Your prolog interpreter is thus returning 'yes' (due to the negation as failure approach of the interpreter), and X remains uninstantiated.
That is why the interpreter shows X = H128, where H128 is a dummy uninstantiated variable.
What was your original intention? It could be that you wanted to state that X is not equal to 3. For inequality many Prolog systems offer dif/2:
?- dif(X,3).
dif(X,3).
In this query we ask for values for X that are not equal to 3. So which values are not equal? Actually, quite a lot: Think of 1, 2, the term 3+3, c, the list [2,3,4] and many more. So giving a concrete answer like X = 4 would exclude many other valid answers. The answer here is however: The query holds for all X that are not equal to 3. The actual evaluation is therefore delayed to a later moment.
?- dif(X,3), X = 3.
false.
Here we got in a situation where X got the value 3 - which does not hold.
?- dif(X,3), X = 4.
X = 4.
And here a concrete valid value is accepted, and the restriciton dif(4,3) is removed.
Yes, it is because the variable X is not bound by the first goal, not(X==3). Actually the not/1 metapredicate can never produce a binding, even if it succeeds. That's because success of not means the inner goal fails. Note that not(X=3) would fail because X=3 can succeed when X is free (and can be bound to value 3).