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
\+
ornot
in Prolog has some weird behaviour compared to the logical not.\+
means negation as finite failure. This means that\+(G)
is considered to betrue
in case Prolog queriesG
, and can not find a way to satisfyG
, and thatG
is finite (eventually the quest to satisfyG
ends).Now if we query
\+(X = Y)
, Prolog will thus aim to unifyX
andY
. In caseX
andY
are (ungrounded) variables, thenX
can be equal toY
. As a resultX \= Y
fails in caseX
andY
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
andY
are already grounded before we callX \= Y
.If we can make for instance the assumption that
X
andY
will be grounded after callingbirth/2
, we can reorder the clause to: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: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/2
andsisters/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).So we can write:
based on your example, the
marriage/3
predicate 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.