Prolog bidirectional predicate

Viewed 1205

I have to create family relations in Prolog for an assignment and I stumbled upon this problem.

man(john).
woman(lisa).
married(john,lisa).

?- married(john,X).
X = lisa.

?- married(X,john).
false.

How to make this predicate work in two ways? If john is married to lisa, then lisa is married to john.

For facts I can only use gender, parent, and married:

man(john).
woman(lisa).
parent(john,steve).
parent(lisa,steve).
married(john,lisa).

That requirement makes this solution unusable for me. I can't just add relation wife(lisa,john). because I have to define wife, husband etc. by myself, like.

wife(X,Y) :- woman(X),married(X,Y).
2 Answers

Instead of trying to make married/2 bidirectional, you could define your predicate wife/2 accordingly. If the first argument of married/2 is always the husband and the second always the wife, just flip the arguments of the second goal:

wife(X,Y) :-
   woman(X),
   married(Y,X).      % <- changed to Y,X instead of X,Y

With your given facts this yields the desired result:

?- wife(X,Y).
X = lisa,
Y = john.

If your facts also include pairs the other way around, e.g.:

woman(ann).
man(anton).
married(ann, anton). 

you can include a second rule (namely your original rule) for wife/2 to deal with such pairs as well:

wife(X,Y) :-
   woman(X),
   married(Y,X).
wife(X,Y) :-          % <- new rule
   woman(X),          
   married(X,Y). 

With the additional rule and facts the above query now yields:

?- wife(X,Y).
X = lisa,
Y = john ;
X = ann,
Y = anton.

If you can't add helper relation (it sounds like homework exercise), try to use predicate @< which operates on the "Standard Order of Terms":

married(A,B) :- A @< B, married(B,A).

Note, however, that this solution brings also some negative aspects (please read this answer).

Related