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.
Related
In Prolog we can write very simple programs like this:
mammal(dog).
mammal(cat).
animal(X) :- mammal(X).
The last line uses the symbol :- which informally lets us read the final fact as: if X is a mammal then it is also an animal.
I am beginning to learn Prolog and trying to establish which of the following is meant by the symbol :-
Implies (⇒)
Entails (⊨)
Provable (⊢)
In addition, I am not clear on the difference between these three. I am trying to read threads like this one, but the discussion is at a level above my capability, https://math.stackexchange.com/questions/286077/implies-rightarrow-vs-entails-models-vs-provable-vdash.
My thinking:
Prolog works by pattern-matching symbols (unification and search) and so we might be tempted to say the symbol :- means 'syntactic entailment'. However this would only be true of queries that are proven to be true as a result of that syntactic process.
The symbol :- is used to create a database of facts, and therefore is semantic in nature. That means it could be one of Implies (⇒) or Entails (⊨) but I don't know which.
Neither. Or, rather if at all, then it's the implication. The other symbols are above, that is meta-language. The Mathematics Stack Exchange answers explain this quite nicely.
So why :- is not that much of an implication, consider:
p :- p.
In logic, both truth values make this a valid sentence. But in Prolog we stick to the minimal model. So p is false. Prolog uses a subset of predicate logic such that there actually is only one minimal model. And worse, Prolog's actual default execution strategy makes this an infinite loop.
Nevertheless, the most intuitive way to read LHS :- RHS. is to see it as a way to generate new knowledge. Provided RHS is true it follows that also LHS is true. This way one avoids all the paradoxa related to implication.
The direction right-to-left is a bit counter intuitive. This direction is motivated by Prolog's actual execution strategy (which goes left-to-right in this representation).
:- is usually read as if, so something like:
a :- b, c .
reads as
| a is true if b and c are true.
In formal logic, the above would be written as
| a ← b ∧ c
Or
| b and c imply a
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).
I am reading through Learn Prolog Now! 's chapter on cuts and at the same time Bratko's Prolog Programming for Artificial Intelligence, Chapter 5: Controlling Backtracking. At first it seemed that a cut was a straight-forward way to mimic an if-else clause known from other programming languages, e.g.
# Find the largest number
max(X,Y,Y):- X =< Y,!.
max(X,Y,X).
However, as is noted down the line this code will fail in cases where all variables are instantiated even when we expect false, e.g.
?- max(2,3,2).
true.
The reason is clear: the first rule fails, the second does not have any conditions connected to it anymore, so it will succeed. I understand that, but then a solution is proposed (here's a swish):
max(X,Y,Z):- X =< Y,!, Y = Z.
max(X,Y,X).
And I'm confused how I should read this. I thought ! meant: 'if everything that comes before this ! is true, stop termination including any other rules with the same predicate'. That can't be right, though, because that would mean that the instantiation of Y = Z only happens in case of failure, which would be useless for that rule.
So how should a cut be read in a 'human' way? And, as an extension, how should I read the proposed solution for max/3 above?
See also this answer and this question.
how should I read the proposed solution for max/3 above?
max(X,Y,Z):- X =< Y, !, Y = Z.
max(X,Y,X).
You can read this as follows:
When X =< Y, forget the second clause of the predicate, and unify Y and Z.
The cut throws away choice points. Choice points are marks in the proof tree that tell Prolog where to resume the search for more solutions after finding a solution. So the cut cuts away parts of the proof tree. The first link above (here it is again) discusses cuts in some detail, but big part of that answer is just citing what others have said about cuts elsewhere.
I guess the take home message is that once you put a cut in a Prolog program, you force yourself to read it operationally instead of declaratively. In order to understand which parts of the proof tree will be cut away, you (the programmer) have to go through the motions, consider the order of the clauses, consider which subgoals can create choice points, consider which solutions are lost. You need to build the proof tree (instead of letting Prolog do it).
There are many techniques you can use to avoid creating choice points you know you don't need. This however is a bit of a large topic. You should read the available material and ask specific questions.
The problem with your code is that the cut is never reached when evaluating your query.
The first step of trying to evaluate a goal with a rule is pattern matching.
The goal max(2,3,2) doesn't match the pattern max(X,Y,Y), since the second and third arguments are the same in the pattern and 3 and 2 don't pattern-match with each other. As such, this rule has already failed at the pattern matching stage, thus the evaluator doesn't get as far as testing X =< Y, let alone reaching the !.
But your understanding of cuts is pretty much correct. Given this code
a(X) :- b(X).
a(X) :- c(X).
b(X) :- d(X), !.
b(X) :- e(X).
c(3).
d(4).
d(5).
e(6).
and the goal
?- a(X).
The interpreter will begin with the first rule, by trying to satisfy b(X). In the process, it discovers that d(4) provides a solution, so binds the value 4 to X. Then the cut kicks in, which discards the backtracking on b(X), thus no further solutions to b(X) are found. However, it does not remove the backtracking on a(X), therefore if you ask Prolog to find another solution then it will find X = 3 through the a(X) :- c(X). rule. If you changed the first rule to a(X) :- b(X), !. then it would fail to find X = 3.
Although the cut means no X = 5 solution is found, if your query is
?- a(5).
then the interpreter will return true. This is because the a(5) calls b(5), which calls d(5), which is defined to be true. The d(4) fact fails pattern matching, therefore it does not trigger the cut like it does when querying a(X).
This is an example of a red cut (see my comment on user1812457's answer). Perhaps a good reason to avoid red cuts, besides them breaking logical purity, is to avoid bugs resulting from this behaviour.
I am just learning prolog and there is a thing I can't get my head over.
Suppose I have the following program
value(v).
a(X) :- not(value(X)).
So a(v). gives me false, as value(v) can be proved correct.
a(w) gives me true, as there is no fact value(w), therefore, even when trying, it can't be proved correct.
In my understanding, requesting a(X). should give me the first possible value that makes value(X) unproveable. There should be an infinite amount of possibilities, as only value(v) is correct.
But why does Prolog keep answering false?
First of all, please use the ISO predicate (\+)/1 instead of not/1.
Second, please don't use (\+)/1 to denote disequality of terms: (\+)/1 is incomplete in Prolog, and thus not logically sound. It is not logical negation, but rather denotes "not provable".
In your case: ?- value(X). succeeds, so it is provable, so ?- \+ value(X). fails although there are instantiations that make the query succeed.
In particular, ?- \+ value(a). succeeds.
So we have:
?- \+ value(V).
false.
But a more specific query succeeds:
?- V = a, \+ value(V).
V = a.
This obviously runs counter to logical properties we expect from pure relations. See logical-purity.
To denote disequality of terms, use dif/2. If your Prolog system does not support dif/2, ask for its inclusion, or use iso_dif/2 as a safe approximation that is logically sound. See prolog-dif for more information.
Prolog operates under "closed world assumption" – it only knows what we told it about. In particular, we've told it nothing about no w, u, or any other stuff, so how could it produce them to us? And why should w come before u, and not vice versa?
The only thing sensible could be to produce (X, dif(X,v)), but it would be the answer to a different question, namely, "how to make a(X) provable?", not the one Prolog is actually answering, namely "is a(X) provable?".
To ease up your cognitive burden, rename the Prolog prompt's replies in your head from true to Yes, and from false to No.
Yes would mean Prolog telling us "yes, I could prove it!", and No – "no, I couldn't prove it."
Also rename "not" to read \+ as not_provable, mentally.
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.