I was reading Learn Prolog Now! and I'm confused about their use of logic and I was hoping someone can clarify the ambiguity of arguments in rules.
For example, on Chapter 1, knowledge base 4 they reference the following rule:
loves(vincent,mia).
They then provide a query:
loves(marsellus,X), woman(X).
and then the make the English statement:
"Now, remember that , means "and", so this query says: is there any individual X such that Marsellus loves X and X is a woman ?"
The key word being, Marsellus loves X.
This is worded in a way that makes me think there is some "logic" tied to the arrangement of arguments, such as to say,
Is it true that loves(vincent,mia). "logically" means:
vincent loves mia?
BUT is it false that
mia loves vincent?
That's what I originally thought but then on Chapter 3, example 2: Descendant they have the following example of:
child(bridget,caroline).
Then the English statement: "That is, Caroline is a child of Bridget"
But if #1 above is true (vincent loves mia), then shouldn't this be read as Bridget is a child of Caroline?
Or does the order of arguments not matter and it's your additional programming that will determine the logic of the arguments?
loves(X, Y) intuitively would mean X loves Y but not Y loves X. But as a programmer, you could assume it's symmetrical. It just wouldn't be as intuitive. It just depends upon how you choose to define it. Prolog Now chose the most intuitive meaning, so loves(X, Y) means X loves Y, but not Y loves X.
Whether child(X, Y) means X is a child of Y or Y is a child of X is up to the programmer. child used by itself as the name of the fact/predicate in this context is a bit ambiguous here (it's not a verb and isn't part of a phrase) and you just have to roll with whatever the Prolog Now site chose as their meaning. When you view the functor as a verb, the arguments are interpreted left to right as expected. So, better, would be to use child_of(X, Y) to mean X is a child of Y so that it's clearer.
Prolog as a language wouldn't care whether you define love(X,Y) as X loves Y or Y loves X. It's probably just a convention that we tend to follow in first order logic.
As to why we'd choose the ordering convention we usually follow, It's probably because the predicate defines a relation between two terms. So the order would depend on how you define the relation.
A predicate r(a,b) means that (a,b) is in the relation r:A->B.
The way i would clear my doubts of the case you've given in the question is:
loves(a,?) ? should anything which a loves. And
child(a,?) ? should be anything which is a child of a.
It would depend on how you define the relation 'child'.
As far as i know ( which isn't far ), There's no hard rule in logic that stops you from defining predicates the way you want. You could define love(X,Y) as 'X loves Y' or 'X is loved by Y' as long as you're consistent.
Related
What is the purpose of this:
route(Town1,Town2,Distance):-
road(Town1,Town2,Distance).
Also, what does ! mean in this context? If someone knows exactly what it means, because all I hear is "cut" without any other explanation.
%TRAVELLING SALESMAN PROBLEM
DOMAINS
town = symbol
distance = integer
PREDICATES
nondeterm road(town,town,distance)
nondeterm route(town,town,distance)
CLAUSES
road("tampa","houston",200).
road("gordon","tampa",300).
road("houston","gordon",100).
road("houston","kansas_city",120).
road("gordon","kansas_city",130).
route(Town1,Town2,Distance):-
road(Town1,Town2,Distance).
route(Town1,Town2,Distance):-
road(Town1,X,Dist1),
route(X,Town2,Dist2),
Distance=Dist1+Dist2, !.
GOAL
route("tampa", "kansas_city", X),
write("Distance from Tampa to Kansas City is ",X),nl.
Prolog programs use recursion heavily, which is why you need a base case for the recursion to stop. Here:
route(Town1,Town2,Distance):-
road(Town1,Town2,Distance).
We're saying "If there's a direct road between Town1 and Town2, then we're done, no need to check for a route through any other town because this is a route, just give me the distance." In other words, we are saying "If there is a defined clause that matches the first two arguments, what must Distance be to fully match it?"
The ! is the cut/1 predicate. It stops backtracking. Here it is, described more thoroughly:
Sometimes it is desirable to selectively turn off backtracking. Prolog provides a predicate that performs this function. It is called the cut/1, represented by an exclamation point (!).
The cut/1 effectively tells Prolog to freeze all the decisions made so far in this predicate. That is, if required to backtrack, it will automatically fail without trying other alternatives.
In the case of your code:
route(Town1,Town2,Distance):-
road(Town1,X,Dist1),
route(X,Town2,Dist2),
Distance=Dist1+Dist2, !.
You are telling Prolog that, if you find a road between Town1 and Town X, and then from Town X there is a route to finish of the path between Town1 and Town2, then recurse; if there is a direct road between X and Town2, then the predicate at the top of your question holds. If not, it will recursively loop. Eventually, Dist2 will have a final value which will float back up to this predicate.
This is where ! comes in. Once you have a route that holds, it says "Stop, don't try and find another route, I only want 1 route. Don't backtrack for any other possible routes." Otherwise, you'd get multiple write("Distance from Tampa to Kansas City is ",X),nl. with different X values, which might not have made sense to the author of this program.
Also, as #DavidTonhofer says, the = should be replaced with is as the latter will force arithmetic evaluation. For example X = 2+4 compares X to the unevaluated expression 2+4, but with is you'll be comparing X to 6.
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).
let's say I have some predicate a/1, now how would I represent b which is true if a fails for some value ?
Unfortunately not doesn't help here , a definition like this :
b(X):- not(a(X)).
means "b is true if for any X a is false"(I want this to work when X isn't instantiated).
How would someone express this ? and what about the general case where more than one (not instantiated) variable exists ?
Is there more known about a/1?
Many Prolog predicates do have purely relational, sound negations.
For example, the unification X = Y can be cleanly stated not to hold by using the constraint dif/2: dif(X, Y) is true iff X and Y are different. It works correctly in all modes of use.
Similarly, CLP(FD) constraints like (#=)/2, (#>)/2 and others all have a completely sound logical negations. For example, you can say X #\= Y to state that X and Y are distinct integers.
A general way to express such issues is to reify the truth values of your predicates. For example, instead of a predicate a/1, consider a predicate a/2, where the second argument denotes whether the predicate holds in this case. You would call this as a(Arg, Truth), and your job is to implement it in such a way that Truth correctly reflects the truth value of a/1 for Arg. You can throw an instantiation_error in cases where you cannot make a sound decision. The preferable way is of course to declaratively express all possible cases using suitable constraints.
In some cases, constraint refication is already available out of the box. For example, you can negate all reifable CLP(FD) constraints using the predicate (#\)/1. Therefore, #\ (X #= Y) is the same as X #\= Y. Boolean constraints provide similar features.
As pointed before, there is no logical negation in Prolog, since there is no closed universe. Prolog negation is a negation-by-failure. This is, something is false whether it can not be prooved to be true.
In practique, not/1 (or '\+'/1) requieres a ground term to behalf as a logical negation.
You may find some experiments with logical negation (closed universes or domains) in some development environments (as far as I remember, Ciao Prolog has something about that). It requieres variables to be declared as having values at some finite domain.
I want to know why the order of quantifiers are important in a logic formula?
When I read books about logic programming, such points are mentioned, but did not say why.
Is there any one could explain with some examples?
Also, how can we determine order of quantifiers from a given logic formula?
Thanks in advance!
You would be well advised to read a book about first-order logic before the books about
logic programming.
Consider the true statement:
1. Everybody has a mother
Let's formalize it in FOL. To keep it simple, we'll say
that the universe of discourse is the set of people, i.e.
our individual variables x, y, z... range over people. Then
1 becomes:
1F. (x)(Ey)Mother(y,x)
which we can read as: For every person x there exists
some person y such that y is the mother of x.
Now let's swap the order of the universal quantifier (x) and existential
quantifier (Ey):
2F. (Ey)(x)Mother(y,x)
That reads: There is some person y such that for every person x,
y is the mother of x. Or in plain English:
2. There is somebody who is the mother of everybody
You see that swapping the quantifiers changes the meaning of the statement,
taking us from the true statement 1 to the false statement 2. Indeed, to the absurdly false statement
2, which entails that somebody is their own mother.
That's why the order of quantifiers matters.
how can we determine order of quantifiers from a given logic formula?
Well, in 1F and 2F, for example, all the variables are already bound by quantifiers,
so there's nothing to determine. The order of the quantifiers is what you see,
left to right.
Suppose one of the variables was free (not bound), e.g.
3F. (Ey)Mother(y,x)
You might read that as: There is someone who is the mother of x, for variable person x.
But this formula really doesn't express any statement. It expresses a unary predicate of persons, the predicate Someone is the mother of x. If you free up the remaining variable:
4F. Mother(x,y)
then you have the binary predicate, or relation: x is the mother of y.
A formula with 1,2,...,n free variables expresses a unary, binary,...,n-ary predicate.
Given a predicate, you can make a statement by binding free variables with quantifiers and/or substituting individual constants for the free variables. From 4F you can make:
(x)(y)Mother(x,y) (Everybody is everybody's mother)
(Ex)(y)Mother(x,y) (Somebody is everybody's mother)
(Ex)(Ey)Mother(x,y) (Somebody is somebody's mother)
(x)Mother(x,Arnold) (Everybody is the mother of Arnold)
(x)Mother(Bernice,x) (Bernice is the mother of everybody)
Mother(Arnold,Bernice) (Arnold is the mother of Bernice)
...
...
and so on ad nauseam.
What this should make clear is that if a formula has free variables, and therefore expresses
a predicate, the formula as such does not imply any particular way of quantifying
the free variables, or that they should be quantified at all.
Say I have the following theory:
a(X) :- \+ b(X).
b(X) :- \+ c(X).
c(a).
It simply says true, which is of course correct, a(X) is true because there is no b(X) (with negation as finite failure). Since there is only a b(X) if there is no c(X) and we have c(a), one can state this is true. I was wondering however why Prolog does not provide the answer X = a? Say for instance I introduce some semantics:
noOrphan(X) :- \+ orphan(X).
orphan(X) :- \+ parent(_,X).
parent(david,michael).
Of course if I query noOrphan(michael), this will result in true and noOrphan(david) in false (since I didn't define a parent for david)., but I was wondering why there is no proactive way of detecting which persons (michael, david,...) belong to the noOrphan/1 relation?
This probably is a result of the backtracking mechanism of Prolog, but Prolog could maintain a state which validates if one is searching in the positive way (0,2,4,...) negations deep, or the negative way (1,3,5,...) negations deep.
Let's start with something simpler. Say \+ X = Y. Here, the negated goal is a predefined built-in predicate. So things are even clearer: X and Y should be different. However, \+ X = Y fails, because X = Y succeeds. So no trace is left under which precise condition the goal failed.
Thus, \+ \+ X = Y does produce an empty answer, and not the expected X = Y. See this answer for more.
Given that such simple queries already show problems, you cannot expect too much of user defined goals such as yours.
In the general case, you would have to first reconsider what you actually mean by negation. The answer is much more complex than it seems at first glance. Think of the program p :- \+ p. should p succeed or fail? Should p be true or not? There are actually two models here which no longer fits into Prolog's view of going with the minimal model. Considerations as these opened new branches to Logic Programming like Answer Set Programming (ASP).
But let's stick to Prolog. Negation can only be used in very restricted contexts, such as when the goal is sufficiently instantiated and the definition is stratified. Unfortunately, there are no generally accepted criteria for the safe execution of a negated goal. We could wait until the goal is variable free (ground), but this means quite often that we have to wait way too long - in jargon: the negated goal flounders.
So effectively, general negation does not go very well together with pure Prolog programs. The heart of Prolog really is the pure, monotonic subset of the language. Within the constraint part of Prolog (or its respective extensions) negation might work quite well, though.
I might be misunderstanding the question, and I don't understand the last paragraph.
Anyway, there is a perfectly valid way of detecting which people are not orphans. In your example, you have forgotten to tell the computer something that you know, namely:
person(michael).
person(david).
% and a few more
person(anna).
person(emilia).
not_orphan(X) :- \+ orphan(X).
orphan(X) :- person(X), \+ parent(_, X).
parent(david, michael).
parent(anna, david).
?- orphan(X).
X = anna ;
X = emilia.
?- not_orphan(X).
X = michael ;
X = david ;
false.
I don't know how exactly you want to define an "orphan", as this definition is definitely a bit weird, but that's not the point.
In conclusion: you can't expect Prolog to know that michael and david and all others are people unless you state it explicitly. You also need to state explicitly that orphan or not_orphan are relationships that only apply to people. The world you are modeling could also have:
furniture(red_sofa).
furniture(kitchen_table).
abstract_concept(love).
emotion(disbelief).
and you need a way of leaving those out of your family affairs.
I hope that helps.