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
actually means:
now
\+ornotin Prolog has some weird behaviour compared to the logical not.\+means negation as finite failure. This means that\+(G)is considered to betruein case Prolog queriesG, and can not find a way to satisfyG, and thatGis finite (eventually the quest to satisfyGends).Now if we query
\+(X = Y), Prolog will thus aim to unifyXandY. In caseXandYare (ungrounded) variables, thenXcan be equal toY. As a resultX \= Yfails in caseXandYare 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
XandYare already grounded before we callX \= Y.If we can make for instance the assumption that
XandYwill be grounded after callingbirth/2, we can reorder the clause to:Prolog has however a predicate
dif/2that 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:Making things simpler
That being said, I think you make the program too complex. We can start with a few definitions:
It is however possible that
brothers/2andsisters/2do 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).So we can write:
based on your example, the
marriage/3predicate is bidirectional: in casemarriage(X,Y,Z)., then there is also a factmarriage(Y,X,Z)..And now we can define:
and that's it.