Prolog difference between statements - prolog

Can someone explain to me why is:
notmarried(P) :- \+(married(P)), male(P).
different then:
notmarried(P) :- male(P), \+(married(P)).

Good question!
The answer has to do with logical purity: in Prolog negation is implemented as negation-as-failure. In general a goal \+ G states that G cannot be proven at this point of time---not that G is logically false.
As a consequence the conjunctions you wrote may not be commutative.

The subject is that a variable in prolog can be bound to some value (X=foo) or unbound (not yet known value).
Now, assume the following facts:
married(tom).
married(john).
What must be after "not married" in
\+married(P), male(P)
?
P can be any value except "tom" or "john". But prolog has no way to store this fact in "P" (not with the basic statements). So, the result of "not married" is "yes, it is possible there some people not married" and P unbound. With P unbound, male(P) takes the first male, and we have the first answer.
Now, the second query:
male(P), \+married(P).
After male, prolog will bound P to one of the males. Now, it will check if this male is married or not, answering yes/not. In case of not, it will backtract to another male, and so on.

Related

Relationship between not found, dif, and \+

Conceptually what's the relationship between false, dif, and \+.
Given this program:
likes(john, mary).
What is being asked exactly when executing the query:
\+ like(john, A).
And why is the answer not:
dif(A, mary).
The more I think about it, the more I'm convinced that I don't understand the meaning of negation in Prolog.
\+ like(john, A)
(This is an malformed query if variable A behind the \+ is unbound at call time: floundering)
\+ is an operator that is defined procedurally:
prove the query on the right of \+
If it succeeds then fail.
In other words, "if you can't find evidence for it, assume it's false" aka. "default negation". An attitude taken in relational databases for one. It is basically a replacement for the problem that Prolog doesn't have strongly negated statements, but turns out to be a welcome extension that the philosophers of logic hadn't even come up with earlier.
dif(A, mary).
Is much simpler: "Make sure that A and mary do not unify on this branch of the computation". A constraint is set up that will cause unification of mary and A to fail, either immediately if A is already bound to mary or later. Compare with A \= mary which states that A and mary do not unification at the time this statement is encountered, and so is not really a "logic statement" at all.
I collected some notes on negation as failure and dif/2 which need to be reworked. Still useful.

Prolog Unification with not()

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.

I am confused on the logic of this particular program

Problem:
Jack is looking at Anne, Anne is looking at George
Jack is married, George is not.
Is a married person looking at an unmarried person?
I am looking at this solution found in this link which entails:
unmarried(X) :- not(married(X)).
unmarried("George").
unmarried("Anne").
married("Jack").
married("Anne").
looking_at("Jack", "Anne").
looking_at("Anne", "George").
check(X, Y):-
looking_at(X,Y),
married(X),
unmarried(Y).
There are several questions immediately apparent once this much is done. For the first part, I was confused as to why Anne is defined as Married("Anne") and Unmarried("Anne"), but I quickly put that aside assuming that it possibly means to define Anne as either married or unmarried
A quick look at SO doesn't help either, as I found only some remotely
related questions; This particular question being the closest one.
Now back to the problem that I have here...
unmarried(X) :- not(married(X)). handles the operation such that if Anne is passed as the first argument of check(_, _)
The programmer for that solution has handled it with a single check(_, _) according to which:
check(Anne,George) will infer:
Anne looking at George
Anne being married
George being unmarried
That compiler produces this result as:
Anne->Jack->Anne->Anne
George->Anne->George->George
At this point, I don't know why the compiler is producing those results. And as far as I know, this is not giving the solution either. In the old desktop version of prolog that I used, check(Anne,George). should have produced a YES, seeing as all the conditions were TRUE(Well I have never tried the online swi-prolog tbh; is it different?)
For check(Jack,Anne) it is:
Jack looking at Anne
Jack being married
Anne being unmarried
I don't see how this necessarily solves the problem. Could someone post a better solution or explain in detail how this is working?
Requirement:
I need a solution for the Problem that I posted at the begining of this question. If you can resolve it from the existing condition that I have posted, thats cool. However, I am also open to alternate ideas and solutions.
First lets look at the puzzle itself. The question "Is a married person looking at an unmarried person?" is clearly a yes/no question. Considering the marital status we have incomplete knowledge(Anne). The people who's marital status we know are not gazing at each other, so we have to consider Anne to find an answer. If we assume that:
Anne is married then the answer is yes because she is looking at the unmarried George.
Anne is not married then the answer is yes because the married Jack is looking at her.
So either way there is a married person looking at an unmarried person, thus the answer to the puzzle is yes.
Regarding the given solution: I think the author tries to model "Anne is either married or not married" by the facts married("Anne") and unmarried("Anne"). However the facts seem to express that Anne is married and unmarried at the same time. Also the rule unmarried(X) :- not(married(X)). in combination with the facts married/1 and unmarried/1 yields the solution "Anne" twice. Thus check/2 also yields the Anne-looks-at-George solution twice:
?- check(X,Y).
X = "Jack",
Y = "Anne" ? ;
X = "Anne",
Y = "George" ? ;
X = "Anne",
Y = "George"
I can see where the author is trying to go with his solution but it isn't really expressing that there is an assumption involved and how the two unique solutions are connected.
My attempt is the following: I would keep four facts from the original version and add another one for Anne:
married(jack).
unmarried(george).
looking_at(jack,anne).
looking_at(anne,george).
unknown(anne).
Then I can make assumptions about people who's marital status I don't know:
person_assumption(A,married) :- unknown(A).
person_assumption(A,unmarried) :- unknown(A).
Now the relevant cases for the yes-answer are: (1) a known unmarried person is being looked at by a known married person and (2) a person P1 is
looking at known unmarried person under the assumtion that P1 is married
AND
being looked at by a known married person under the assumption that P1 is unmarried
The predicate problematicgaze/1 is modeling these observations:
problematicgaze((P1-P2)) :- % case (1)
married(P1),
unmarried(P2),
looking_at(P1,P2).
problematicgaze((if_married(P1)-P2,P3-if_unmarried(P1))) :- % case (2)
assumedproblematic(if_married(P1),P2),
assumedproblematic(P3,if_unmarried(P1)).
assumedproblematic(if_married(P1),P2) :-
person_assumption(P1,married),
unmarried(P2),
looking_at(P1,P2).
assumedproblematic(P1,if_unmarried(P2)) :-
person_assumption(P2,unmarried),
married(P1),
looking_at(P1,P2).
This breaks down to: either I get a solution and the answer is yes or the predicate fails and the answer is no. So I ask if there is a problematic gaze in the given situation:
?- problematicgaze(G).
G = (if_married(anne)-george,jack-if_unmarried(anne)) ? ;
no
As expected there is no answer from the first rule of problematicgaze/1 but from the second. No matter which assumption is taken for Anne a married person is looking at an unmarried one. Other than that no solution is found.
The solution to which you have linked is not correct. A pointed out in the comments, I am not sure how this gives answers:
?- check(X, Y).
X = "Jack",
Y = "Anne" ;
X = "Anne",
Y = "George" ;
X = "Anne",
Y = "George".
Please if someone knows the program was meant to be used, explain. I am afraid I am just missing something.
Here is one attempt at a real solution. First, we leave the ground facts exactly as given:
looking_at(jack, anne).
looking_at(anne, george).
married(jack).
unmarried(george).
I will now define a predicate solution/2 which has the solution and any possible bindings that explain it. There are three possible solutions, if I understand: "yes", "no", and "undetermined". In the case of a "yes" answer:
solve(yes, married_unmarried(A, B)) :-
married(A),
looking_at(A, B),
unmarried(B).
The "no" case is a bit different. It is supposed to say:
For all A looking at a B, either A is unmarried or B is married.
With SWI-Prolog and forall/2, you can write:
solve(no, false) :-
forall(looking_at(A, B),
( unmarried(A) ; married(B) )).
This is equivalent to:
solve(no, false) :-
\+ ( looking_at(A, B),
\+ ( unmarried(A) ; married(B) ).
The undetermined case is more interesting, but we could try and cheat:
solve(undetermined, B) :-
\+ solve(yes, B),
\+ solve(no, B).
We can neither prove that someone is looking nor that no one is looking.

prolog using recursion to find successor

I'm trying to learn prolog now and I started recursion topic. Came across this example for successor.
numeral(0).
numeral(succ(X)) :- numeral(X)
I do understand how it works in theory. It takes the number X and succ increments it. My questions here is, is succ an in-built predicate? Or is there something else going on in this example. Example taken from learnprolognow.org
Then I came across this exercise
pterm(null).
pterm(f0(X)) :- pterm(X).
pterm(f1(X)) :- pterm(X).
It is meant to represent binary, that is 0 is f0(null), 1 is f1(null), 2(10) is f0(f1(null)), 3(11) is f1(f1(null)) etc.
The question asks to define predicate (P1, P2) so that P2 is the successor of P1 by using pterms.
Could someone explain this question in more detail for me?
The way I see it now, I have to traverse back through P1 until I hit the end and then compare it to P2, but I'm not exactly sure about the syntax.
Any hints would be useful
succ is a compound term, not a built-in predicate.
Taking the two clauses in order you have:
numeral(0).
This means numeral(0) is true, i.e. 0 is a numeral
numeral(succ(X)) :- numeral(X)
This means numeral(succ(X)) is true if you can show that numeral(X) is true.
If you ask the query:
?- numeral(succ(succ(0)).
Then prolog will say True: numeral(succ(succ(0)) is true if numeral(succ(0)) is true. And numeral(succ(0)) is true if numeral(0) is true. And we know numeral(0) is true.
If you ask
?- numeral(X).
Then prolog will reply X=0 then X=succ(0) then X=succ(succ(0)) and so on as it finds terms which satisfy your clauses.
Now to answer your pterm question...
First think about the structure you are building. Its a binary number and the outermost term is the least significant bit. Here are some examples for things which are true:
1: succ(f1(null),f0(f1(null))
2: succ(f0(f1(null)),f1(f1(null))
3: succ(f1(f1(null)),f0(f0(f1(null)))
If you look at the examples for 2 and 3 above then you should be able to derive three cases of interest. As a hint the first case is that if the term is of the form f0(X) then the successor is f1(X).
seems that inspecting the top level argument could be enough. Just an hint
psucc(pterm(f0(X)), pterm(f1(f0(X)))).
...

Why double negation doesn't bind in Prolog

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.

Resources