Alternative to express “Commutativity” in Prolog?

2019-04-26 03:46发布

问题:

as a beginner to Prolog, I found the commutative expression in Prolog are quite not intuitive.

for example if I want to express X and Y are in one family, like:

family(X,Y) :-
      married(X,Y);
      relative(X,Y);
      father_son(X,Y).

I should also add the following to the definition, in order to make it "commutative":

      married(Y,X);
      relative(Y,X);
      father_son(Y,X).

But we use Prolog, because we want to write elegant code... so, I'd hope to add only one line(instead of the above three) to the original :

      family(Y,X).

Here is the POINT. it leads to untermination! why is prolog no so "logical"? and is there an alternative to this neat one line expression that doesn't lead to untermination?

Nice weekends! watt

回答1:

The problem with family(X,Y) :- family(Y,X). part of the rule is that it keeps unifying unconditionally with itself at each level, and keeps recursing down; there is no exit condition out of this recursion.

You should make the argument swap at the level above:

family(X,Y) :-
    is_family(X,Y);
    is_family(Y,X).

is_family(X,Y) :-
    married(X,Y);
    relative(X,Y);
    father_son(X,Y).

Alternatively, you could make underlying rules below symmetric where it makes sense:

is_married(X,Y) :-
    married(X,Y);
    married(Y,X).

is_relative(X,Y) :-
    relative(X,Y);
    relative(Y,X).

You could now rewrite your family rule as follows:

family(X,Y) :-
    is_married(X,Y);
    is_relative(X,Y);
    father_son(X,Y);
    father_son(Y,X).


回答2:

How about:

relatives(X,Y) :-
  married(X,Y);
  relative(X,Y);
  father_son(X,Y).

family(X,Y) :-
  relatives(X,Y);
  relatives(Y,X).