Search code examples
prologpredicatesymmetric

Prolog — symmetrical predicates


I have to simulate family tree in prolog. And i have problem of symetrical predicates. Facts:

parent(x,y).
male(x).
female(y).
age(x, number).

Rules:

blood_relation is giving me headache. this is what i have done:

blood_relation(X,Y) :- ancestor(X,Y).
blood_relation(X,Y) :- uncle(X,Y)
                    ; brother(X,Y)
                    ; sister(X,Y)
                    ; (mother(Z,Y),sister(X,Z))
                    ; (father(Z,Y),sister(X,Z))
                    ; (father(Z,Y),brother(X,Z)).
blood_relation(X,Y) :- uncle(X,Z)
                    , blood_relation(Z,Y).

and I am getting i think satisfactory results(i have double prints - can i fix this), problem is that i want that this relation be symmetrical. It is not now.

blood_relation(johns_father, john):yes 
blood_relation(john,johns_father): no

so..is there a way to fix this. And i need query: All pairs that are not in blood_relation..

Update:

What kinds of relationships is the first statement supposed to satisfy? blood_relation(X,Y):-blood_relation(X,Y).

sorry..it is a bad copy/paste..it

blood_relation(X,Y):-ancestor(X,Y).

Now fixed above.

here are other rules:

father(X,Y) :-
  parent(X,Y),male(X).  
mother(X,Y) :-
  parent(X,Y),female(X).  
brother(X,Y) :-
  parent(Z,X),parent(Z,Y),
  male(X).  
sister(X,Y) :-
  parent(Z,X),parent(Z,Y),
  female(X).  
grandFather(X,Y) :-
  parent(Z,Y),parent(X,Z),
  male(X).  
grandMother(X,Y) :-
  parent(Z,Y),
  parent(X,Z),female(X).  
uncle(X,Y) :-
  mother(Z,Y),brother(X,Z).  
ancestor(X,Y) :-
  ancestor(X,Y).  
ancestor(X,Y) :-
  parent(X,Z),ancestor(Z,Y).

Mother's brother is in uncle definition. It's kind of strange. I've got rules that I need to implement, and I don't know how I can implement rules besides that. I'm just confused.

Any idea how to make blood_relation symmetric? And not_blood_relation is a new rule. And I need query. This one is really giving me headache. Maybe because relation is written like crap.

And there are no more facts. That's all. All rules, and all facts.

query.. not(blood_relation(X,Y)) doesn't work, and I really don't know why. For example query:

age(X,Y), Y>18,  
not(parent(X,Z)),write(X),nl,fail.

works just fine


Solution

  • A bit looks like a homework, isn't it...

    One trick which most of beginners of prolog don't think of is list pattern matching. Think of a tree like [a1,[[a2],[b2,[[e3],[f3]]],[c2]]] as in <tree>=[root,[<tree1>,<tree2>,...]]:

    %Y is immediate child of X?
    child(X,Y,[X|S]) :- member([Y|_],S).
    
    %pick one tree in S and check
    child(X,Y,[X|S]) :- member([Z|SS],S),child(Z,Y,[Z|SS]).
    
    %X and Y end up with same root?
    sib(X,Y,[R|T]) :- child(R,X,[R|T]), child(R,Y,[R|T]).
    

    I think you can improve upon this like, using pairs as roots, adding genders, giving names to specific relations of members of the tree...