Alternative to express "Commutativity" in Prolog?
Asked Answered
M

2

9

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

Mcnally answered 21/4, 2012 at 10:0 Comment(0)
H
11

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).
Handcraft answered 21/4, 2012 at 10:13 Comment(2)
i would also suggest using separate facts instead of ;Blowzy
@AlexanderSerebrenik Absolutely - I wanted to stay close to the style of the original. However, back in my Prolog days I preferred multiple rules over ; for readability and ease of debugging.Handcraft
F
1

How about:

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

family(X,Y) :-
  relatives(X,Y);
  relatives(Y,X).
Firebrand answered 21/4, 2012 at 10:6 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.