0

I have these facts and rules :

male(roelof).
male(mans). 
male(ronald).
male(jan).

female(chantal).
female(marie).
female(gerda).
female(dagmar).
female(denise).
female(kimberly).


parent(mans,gerda).
parent(mans,roelof).
parent(marie,gerda).
parent(marie,roelof).
parent(dagmar,denise).
parent(dagmar,kimberly).
parent(ronald,denise).
parent(ronald,kimberly).
parent(chantal,tamara).
parent(roelof,tamara).
parent(jan,chantal).
parent(jan,dagmar).

father_child(Father, Child) :-
 parent(Father, Child),
 male(Father).

mother_child(Mother, Child) :-
 parent(Mother, Child),
female(Mother).

child_father_mother(Child, Father, Mother) :-
 father_child(Father, Child),
 mother-child(Mother, Child).  

same_father(Child, Sibling) :-
 father_child(Father, Child),
 father_child(Father, Sibling).

same_mother(Child, Sibling) :-
  mother_child(Mother, Child),
  mother_child(Mother, Sibling).

siblings(Child, Sibling) :-
  same_father(Child, Sibling),
  Child \= Sibling.
siblings(Child, Sibling) :-
  same_mother(Child, Sibling),
  Child \= Sibling.

display_siblings(X,Y) :-
     setof(X-Y, (siblings(X,Y), \+X=Y), Sibs),
               member((X-Y,Y), Sibs),
               \+ (Y@<X, member((Y,X), Sibs)).

But when I do display_siblings I expected to see roelof-gerda. But the output is only x=roelof

What did I do wrong. Im a beginner at Prolog and try to understand how this works.

Roelof

Edit 1: Could this be a solution: How can I prevent duplicates in prolog

Edit 2: I will do but I still do not understand why 'setof(X-Y, (siblings(X,Y), X @< Y), Sibs),write(Sibs).' is wrong. It works in both cases display_'siblings(gerda,X)' and 'display_siblings(X,Y)'

Community
  • 1
  • 1
user3426797
  • 35
  • 1
  • 6

1 Answers1

1

Most of your problem lies in your display_siblings predicate:

display_siblings(X,Y) :-
     setof(X-Y, (siblings(X,Y), \+X=Y), Sibs),
     member((X-Y,Y), Sibs),
     \+ (Y@<X, member((Y,X), Sibs)).

In the second line, the \+X=Y is superfluous since siblings already enforces that they are different. So that can be:

setof(X-Y, siblings(X,Y), Sibs),

The next line is querying whether (X-Y,Y) is a member of Sibs. However, Sibs consists of X-Y terms which will never match an (X-Y,Y) term. So this call to member will always fail. It should probably be:

member(X-Y, Sibs),

And then the last line is overly complex if all you want to do is eliminate symmetrical duplicates. You can simply use X @< Y and for efficiency, make this part of the setof check:

display_siblings(Sibs) :-
     setof(X-Y, (siblings(X,Y), X @< Y), Sibs).

This will yield:

?- display_siblings(Sibs).
Sibs = [chantal-dagmar, denise-kimberly, gerda-roelof].

If you want to select all of the siblings for a given person and still avoid the symmetry redundancies, you may need to process out those redundancies after the setof:

display_siblings(X, Sibs) :-
    setof(A-B, ((X = A ; X = B), siblings(A,B)), SibPairs),
    pack(SibPairs, Sibs).

pack([X-Y|T], Sibs) :-
    pack(T, SibList),
    (  member(Y-X, SibList)
    -> SibList = Sibs
    ;  Sibs = [X-Y|SibList]
    ).
pack([], []).

?- display_siblings(gerda, Sibs).
Sibs = [roelof-gerda].
lurker
  • 56,987
  • 9
  • 69
  • 103
  • Wierd, I changed it as you said and I see these solutions. display_siblings(gerda,X) true. and display_siblings(X,Y) gives true.The member part is no more a part of the rule? – user3426797 Mar 17 '14 at 16:10
  • @user3426797 if I understand the meaning of your predicate correctly, you don't need `member`. – lurker Mar 17 '14 at 17:08
  • oke, then somehow your rule does not work at my place. When I do this : http://pastebin.com/GtnpUkpn. I only see true or false. – user3426797 Mar 17 '14 at 17:51
  • @user3426797 if you put all your other data and predicates in (not including your version of `display_siblings`) and you enter `setof(X-Y, (siblings(X,Y), X @< Y), Sibs).` what do you get? – lurker Mar 17 '14 at 18:27
  • Then I see the outcome as you said. What is then the difference between enter in the prompt or making a rule of it. – user3426797 Mar 17 '14 at 18:41
  • found it. I have to add ,write(Sibs). – user3426797 Mar 17 '14 at 18:49
  • @user3426797 I had an error: instead of `write` you can have `Sibs` as an argument to `display_siblings`. I just forgot to add the argument. I updated the answer accordingly. Also, `X` and `Y` aren't necessary as arguments since they're part of the `setof`, not the solution or inputs. – lurker Mar 17 '14 at 19:06
  • When I changed that and so display_siblings(gerda). I see only false. When I do displays(X) I see the right answer. – user3426797 Mar 17 '14 at 19:15
  • @user3426797 That's because `display_siblings(Sibs)` assumes `Sibs` is a list of all sibling relationships. I think I misunderstood a little of what you wanted `display_siblings` to do. I will fix that... – lurker Mar 17 '14 at 20:32
  • I saw that you changed it.Can you explain to me what pack does. What is T and is it correct that -> is if then ? Personally I find the first one easier with using write(Sibs). – user3426797 Mar 17 '14 at 21:44
  • @user3426797 In this case, since we're trying to find a given `X`, I couldn't use `setof` to eliminate `X-Y` if `Y-X` existed. So they both might exist in the list. `pack` will remove `X-Y` if `Y-X` exists so you don't have both. If you just remove the `pack` query in the `display_siblings` predicate, you'll see what I mean when you run `display_siblings`. – lurker Mar 17 '14 at 21:55