0

I'm trying to construct a familiy tree in prolog, but when entering siblings(X,Y). as a query I get duplicates prints, anyone knows why?

for ex:

parent_of(abraham, herb).
parent_of(mona, herb).
parent_of(abraham, homer).
parent_of(mona, homer).

my rule is:

sibilings(P1,P2):-
parent_of(Parent,P1), parent_of(Parent,P2), P1 \= P2.

I know it's printing twice because it is printing once for each parent, but I'm new in Prolog and I don't know how to fix it.

lurker
  • 56,987
  • 9
  • 69
  • 103

1 Answers1

0

Well, logically, Prolog is doing the right thing. You're saying P1 and P2 are siblings if P1 and P2 are different but share a parent. When you ask this to generate, it's going to locate P1 = herb, P2 = homer, Parent = abraham, then it's going to locate P1 = herb, P2 = homer, Parent = mona. You didn't surface Parent in the head of the rule, but the proof that Prolog found is different, so it's a different solution.

Later on, Prolog is also going to notice taht P1 = homer, P2 = herb, Parent = abraham, and give you a third identical solution. Then it'll notice that Parent = mona and give them to you a fourth time.

You can eliminate half of the extra solutions by introducing an ordering constraint on the siblings. You'd be saying P1 is alphabetically earlier than P2, basically:

siblings(S1, S2) :- parent_of(Parent, S1), parent_of(Parent, S2), S1 @> S2.

You'll still get the duplicates about other parents though. This is kind of a cheat anyway, because you're after a property of the entire result set, but you are inside a rule for generating one result. I confess I don't know offhand a nice trick for handling the duplicates you get from the siblings having the same father and mother. Maybe another answerer will arrive with the obvious thing I'm not thinking of.

Another approach would be to gather up the unique solutions, which would look like this:

?- setof(S1-S2, siblings(S1, S2), Solutions).
Solutions = [homer-herb].

Now Prolog is making the results unique by putting them into a set for you.

Daniel Lyons
  • 22,421
  • 2
  • 50
  • 77