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\=: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: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:
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:(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)