2
votes
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 .
1
That's the problem here. When I press ";" I get an answer "false". I try another simple statement to test if I can use ";" to get another answer and I succeed. But in this case, I can't...ruan xun
Try dif(X, Y) in place of X \= Y. dif(X, Y) is the more relational way of saying X and Y are different.lurker

1 Answers

1
votes

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.