Existence Exception in Prolog Program - prolog

I'm trying to write a rule in my prolog program that determines if someone is the brother of someone else.
For example, if I type brother_of(chris, X) it will return christy because chris is the brother of christy. However, when I type this I get an existence exception. I've included facts to cover everything, but maybe it's a problem in my rule definition? The code is below.
/* Facts */
female(ella).
female(jodi).
female(sonya).
female(jane).
female(christy).
female(mary).
male(arnold).
male(chris).
male(louis).
male(mark).
father(arnold).
father(louis).
father(mark).
mother(ella).
mother(jodi).
mother(jane).
mother(mary).
father_of(arnold, chris). /* arnold is the father of chris */
father_of(arnold, christy).
father_of(louis, mark).
father_of(mark, arnold).
mother_of(mary, chris).
mother_of(mary, christy).
mother_of(jane, arnold).
mother_of(ella, sonya).
mother_of(jodi, ella).
mother_of(jodi, mark).
/* Rules */
brother_of(X, Y) :-
male(X),
((father_of(Z, X), father_of(Z, Y));
(mother_of(W, X), mother_of(W, Y))),
X =\= Y.

The operator =\= is used in arithmetic only (AFAIK), to see if two terms are different (non-unifiable) use the operator \=:
X \= Y.
Update: a brief introduction to the cut (!) goal: when the cut is used in a predicate, it means no more answers should be searched besides the already found ones (i.e. you are "cutting the remaining branches" in the search tree). Example:
first_child(X,Y) :-
father_of(X,Y), !.
?- first_child(arnold,Y).
Y = chris ;
no
After the cut is reached, all choice points before the cut are discarded (but new ones can be created after it). In you example, you know that if X and Y have the same father, it's irrelevant if they also have the same mother. So you can place the cut right after the "common father" part succeeds:
brother_of(X, Y) :-
male(X),
((father_of(Z, X), father_of(Z, Y), X \= Y, !); # If cut is reached, will not run the next line
(mother_of(W, X), mother_of(W, Y), X \= Y)).
Note however that using cut has many pitfalls (refer to "green cut" vs "red cut" in the linked Wikipedia article), but it's too much to describe here. (note how I repeated X \= Y - if I didn't do that the program would fail sometimes)
Lastly, I'd also like to point out that using ; is often discouraged when writing Prolog code (you can use when needed though). Instead, write it in two clauses:
brother_of(X, Y) :-
male(X),
father_of(Z, X),
father_of(Z, Y),
X \= Y,
!.
brother_of(X, Y) :-
male(X),
mother_of(W, X),
mother_of(W, Y),
X \= Y.
(this ; vs two clauses is a bit subjective, though, so I won't argue too much about it... just know that both ways are possible, and will produce the same result)

Related

negation \+ and vanilla meta-interpreter

The following is the classic "textbook" vanilla meta-interpreter for prolog.
% simplest meta-interpreter
solve(true) :- !.
solve((A,B)):- !, solve(A), solve(B).
solve(A) :- clause(A,B), solve(B).
The following is simple program which establishes facts two relations which are "positive" and one relation which makes use of negation by failure \+.
% fruit
fruit(apple).
fruit(orange).
fruit(banana).
% colour
yellow(banana).
% Mary likes all fruit
likes(mary, X) :- fruit(X).
% James likes all fruit, as long as it is yellow
likes(james, X) :- fruit(X), yellow(X).
% Sally likes all fruit, except yellow fruit
likes(sally, X) :- fruit(X), \+ (yellow(X)).
The meta-interpeter can handle goals related to the first two relations ?-solve(likes(mary,X)) and ?- solve(likes(james,X)_.
However it fails with a goal related to the third relation ?- solve(likes(sally,X). The swi-prolog reports a stack limit being reached before the program crashes.
Question 1: What is causing the meta-interpreter to fail? Can it be easily adjusted to cope with the \+ negation? Is this related to the sometimes discussed issue of built-ins not being executed by the vanilla meta-interpreter?
Question 2: Where can I read about the need for those cuts in the vanilla meta-interpreter?
Tracing suggests the goal is being grown endlessly:
clause(\+call(call(call(call(yellow(apple))))),_5488)
Exit:clause(\+call(call(call(call(yellow(apple))))),\+call(call(call(call(call(yellow(apple)))))))
Call:solve(\+call(call(call(call(call(yellow(apple)))))))
Call:clause(\+call(call(call(call(call(yellow(apple)))))),_5508)
Exit:clause(\+call(call(call(call(call(yellow(apple)))))),\+call(call(call(call(call(call(yellow(apple))))))))
Call:solve(\+call(call(call(call(call(call(yellow(apple))))))))
Change solve(A) into:
solve(Goal) :-
writeln(Goal),
sleep(1),
clause(Goal, Body),
solve(Body).
... and we see:
?- solve_mi(likes(sally,X)).
likes(sally,_8636)
fruit(_8636)
\+yellow(apple)
\+call(yellow(apple))
\+call(call(yellow(apple)))
\+call(call(call(yellow(apple))))
...
clause/2 determines the body of \+yellow(apple) to be \+call(yellow(apple)), which is not a simplification.
Can use instead:
solve_mi(true) :-
!.
solve_mi((Goal1, Goal2)):-
!,
solve_mi(Goal1),
solve_mi(Goal2).
solve_mi(\+ Goal) :-
!,
\+ solve_mi(Goal).
solve_mi(Goal) :-
clause(Goal, Body),
solve_mi(Body).
Result in swi-prolog:
?- solve_mi(likes(sally,X)).
X = apple ;
X = orange ;
false.
I'm using solve_mi because solve conflicts with e.g. clpBNR, and I'm not using variable names A and B because they convey no meaning.
For understanding the cuts, I'd recommend gtrace, to see the unwanted unification with other goals that would otherwise take place.

Prolog query not terminating

This is a very basic query, but I'm new to prolog and have trouble finding why this query does not terminate:
% fact
progeny(dexter, mark).
progeny(mark, bill).
progeny(bill, lisa).
% rule
progeny(X, Y) :- progeny(X, Z), progeny(Z, Y).
The query, progeny(dexter, X), gives mark, bill and lisa, but does not terminate.
Whereas the query, progeny(Y, lisa), gives bill and dexter and does not terminate (this query answer also misses mentioning mark).
It should be noted that I am using the same name for fact and rule to test for some values.
Any help or clarification for this problem would be much appreciated.
You need to define another predicate that will act as transitive relation. The code below works just as fine (notice the predicate progenyt that is the actual transitive relation).
progeny(dexter, mark).
progeny(mark, bill).
progeny(bill, lisa).
progenyt(X, Y) :- progeny(X, Y).
progenyt(X, Y) :- progeny(X, Z), progenyt(Z, Y).
Clarification
When you write progeny(X, Y) :- progeny(X, Z), progeny(Z, Y)., you will, at some point, have prolog trying to match progeny(dexter, Y) :- progeny(dexter, lisa), progeny(lisa, Y)., which is the moment where prolog gets 'confused'.
Namely, it will try to match progeny(lisa, Y) with some fact, which will fail for all entries. Then, prolog will try rule progeny(lisa, Y) :- progeny(lisa, Z), progeny(Z, Y)., which calls for evaluating progeny(lisa, Z). Here you are met with stack overflow, because for progeny(lisa, Y) to succeed, progeny(lisa, Z) has to succeed as well, which induces sort of infinite loop, and that is why your query never terminates.
In the solution I've posted, that can never happen, because for progenyt(lisa, Y) to succeed, progeny(lisa, Z) has to, and that never happens (it fails for all facts). Therefore, it will produce only those three results and will terminate immediately afterwards.
Note that, if progeny and progenyt were to be swapped in the last line, the query will also run into the same problem as before (for progenyt(lisa, Y) to succeed, progenyt(lisa, Z) has to succeed as well first, will causes the infinite loop).
You can also use tabling. Read the docs I linked for background, explanations, details.
To fix your program, you just add a table directive for your predicate progeny/2.
:- table progeny/2.
% fact
progeny(dexter, mark).
progeny(mark, bill).
progeny(bill, lisa).
% rule
progeny(X, Y) :- progeny(X, Z), progeny(Z, Y).
You should now get:
?- [progeny].
true.
?- progeny(dexter, X).
X = bill ;
X = mark ;
X = lisa. % query terminates
?- progeny(Y, lisa).
Y = bill ;
Y = dexter ;
Y = mark. % no missing solutions, query terminates.

Finding the path length of an Acyclic Graph in Prolog

Okay, so I have the graph:
and I want to be able to create a rule to find all the paths from X to Y and their lengths (number of edges). For
example, another path from a to e exists via d, f, and g. Its length is 4.
So far my code looks like this:
edge(a,b).
edge(b,e).
edge(a,c).
edge(c,d).
edge(e,d).
edge(d,f).
edge(d,g).
path(X, Y):-
edge(X, Y).
path(X, Y):-
edge(X, Z),
path(Z, Y).
I am a bit unsure how I should approach this. I've entered a lot of rules in that don't work and I am now confused. So, I thought I would bring it back to the basics and see what you guys could come up with. I would like to know why you done what you done also if that's possible. Thank you in advance.
This situation has been asked several times already. Firstly, your edge/2 predicates are incomplete, missing edges like edge(c,d), edge(f,g), or edge(g,e).
Secondly, you need to store the list of already visited nodes to avoid creating loops.
Then, when visiting a new node, you must check that this new node is not yet visited, in the Path variable. However, Path is not yet instanciated. So you need a delayed predicate to check looping (all_dif/1). Here is a simplified version using the lazy implementation by https://stackoverflow.com/users/4609915/repeat.
go(X, Y) :-
path(X, Y, Path),
length(Path, N),
write(Path), write(' '), write(N), nl.
path(X, Y, [X, Y]):-
edge(X, Y).
path(X, Y, [X | Path]):-
all_dif(Path),
edge(X, Z),
path(Z, Y, Path).
%https://stackoverflow.com/questions/30328433/definition-of-a-path-trail-walk
%which uses a dynamic predicate for defining path
%Here is the lazy implementation of loop-checking
all_dif(Xs) :- % enforce pairwise term inequality
freeze(Xs, all_dif_aux(Xs,[])). % (may be delayed)
all_dif_aux([], _).
all_dif_aux([E|Es], Vs) :-
maplist(dif(E), Vs), % is never delayed
freeze(Es, all_dif_aux(Es,[E|Vs])). % (may be delayed)
Here are some executions with comments
?- go(a,e).
[a,b,e] 3 %%% three nodes: length=2
true ;
[a,c,d,f,g,e] 6
true ;
[a,c,f,g,e] 5
true ;
[a,d,f,g,e] 5
true ;
false. %%% no more solutions
Is this a reply to your question ?

Can't show the second answer in Prolog

sisters(mary,catherine).
sisters(catherine,mary).
brothers(john,simone).
brothers(simone,john).
marriage(john,mary,2010).
marriage(mary,john,2010).
marriage(kate,simone,2009).
marriage(simone,kate,2009).
marriage(catherine,josh,2011).
marriage(josh,catherine,2011).
birth(mary,johnny).
birth(mary,peter).
birth(catherine,william).
birth(kate,betty).
givebirthyear(mary,peter,2015).
givebirthyear(mary,johnny,2012).
givebirthyear(catherine,william,2012).
givebirthyear(kate,betty,2011).
siblings(X,Y) :-
birth(Parent,X),
birth(Parent,Y).
cousins(X,Y) :-
birth(Xparent,X),
birth(Yparent,Y),
sisters(Xparent,Yparent).
cousins(X,Y) :-
X \= Y,
birth(Xmom,X),
birth(Ymom,Y),
marriage(Xmom,Xdad,_),
marriage(Ymom,Ydad,_),
brothers(Xdad,Ydad).
I don' know what's happening in my code. When I input
cousins(betty,johnny).
and
cousins(william,johnny).
The prolog says true. But when I entered
cousins(S,johnny).
THe prolog says S = william but didn't show me that S = betty. I don't really know what's happening. Need help.
Here is the prolog result I got.
?- cousins(S,johnny).
S = william ;
false.
?- cousins(betty,johnny).
true.
?- cousins(william,johnny).
true .
The problem
The reason this happens is because
X \= Y,
actually means:
\+(X = Y).
now \+ or not in Prolog has some weird behaviour compared to the logical not. \+ means negation as finite failure. This means that \+(G) is considered to be true in case Prolog queries G, and can not find a way to satisfy G, and that G is finite (eventually the quest to satisfy G ends).
Now if we query \+(X = Y), Prolog will thus aim to unify X and Y. In case X and Y are (ungrounded) variables, then X can be equal to Y. As a result X \= Y fails in case X and Y are free variables.
So basically we can either use another predicate that for instance puts a constraint on the two variables that is triggered when the variables are grounded, or we can reorder the body of the clause, such that X and Y are already grounded before we call X \= Y.
If we can make for instance the assumption that X and Y will be grounded after calling birth/2, we can reorder the clause to:
cousins(X,Y) :-
birth(Xmom,X),
birth(Ymom,Y),
X \= Y,
marriage(Xmom,Xdad,_),
marriage(Ymom,Ydad,_),
brothers(Xdad,Ydad).
Prolog has however a predicate dif/2 that puts a constraint on the two variables, and from the moment the two are grounded, it will fail if the two are equal. So we can use it like:
cousins(X,Y) :-
dif(X,Y),
birth(Xmom,X),
birth(Ymom,Y),
marriage(Xmom,Xdad,_),
marriage(Ymom,Ydad,_),
brothers(Xdad,Ydad).
Making things simpler
That being said, I think you make the program too complex. We can start with a few definitions:
two people are slibings/2 if they are brothers/2 or sisters/2.
slibings(X,Y) :-
brothers(X,Y).
slibings(X,Y) :-
sisters(X,Y).
It is however possible that brothers/2 and sisters/2 do not provide all information. Two people are also slibings if they have the same mother (we will assume that people do not divorce here, or at least not give birth to other children after they remarry).
slibings(X,Y) :-
dif(X,Y),
birth(Mother,X),
birth(Mother,Y).
a parent/2 of a person is the mother of the person or the father (the person that married the mother).
So we can write:
parent(Mother,X) :-
birth(Mother,X).
parent(Father,X) :-
birth(Mother,X),
marriage(Father,Mother,_).
based on your example, the marriage/3 predicate is bidirectional: in case marriage(X,Y,Z)., then there is also a fact marriage(Y,X,Z)..
And now we can define:
two people are cousins if there parents are slibings:
cousins(X,Y) :-
parent(MF1,X),
parent(MF2,Y),
slibings(MF1,MF2).
and that's it.

Function not in prolog

sibling(X, Y):- father(Z, X), father(Z, Y), not (X=Y).
sister(X, Y):- father(Z, X), father(Z, Y), female(X).
brother(X, Y):- father(Z, X), father(Z, Y), male(X).
i'm having a bit problem with using the not function. i've tried not X=Y. but to no avail, the sibling rule still produce error.
if i were to delete the not x=y, the output will be a bit kind of "ugly".
how should i write the not function?
The ISO predicate implementing not provable is called (\+)/1.
However, as #coder explains in the comments, it is much better to use dif/2 to express that two terms are different.
dif/2 is a pure predicate that works correctly in all directions, also if its arguments are not yet instantiated.
For example, with (\+)/1, we get:
?- \+ (X = Y ).
false.
No X and Y exist that satisfy this goal, right? Wrong:
?- X = a, Y = b, \+ (X = Y ).
X = a,
Y = b.
In contrast, with dif/2:
?- dif(X, Y).
dif(X, Y).
and in particular:
?- X = a, Y = b, dif(X, Y).
X = a,
Y = b.
See prolog-dif for more information. dif/2 is with us since the very first Prolog system. I strongly recommend you use it.
SWI Prolog has no notoperator. it can be used as a regular compound term, e.i. not(X).
It must be no space between functor and open parenthesis:
foo( argument list ).
This is the cause of the error.
SWI Prolog suggests ISO-standard replacement for not/1: (\+)/1

Resources