Is there any logical difference between these two implementations of a variant predicate?
variant1(X,Y) :-
subsumes_term(X,Y),
subsumes_term(Y,X).
variant2(X_,Y_) :-
copy_term(X_,X),
copy_term(Y_,Y),
numbervars(X, 0, N),
numbervars(Y, 0, N),
X == Y.
Neither
variant1/2
norvariant2/2
implement a test for being a syntactic variant. But for different reasons.The goal
variant1(f(X,Y),f(Y,X))
should succeed but fails. For some cases where the same variable appears on both sides,variant1/2
does not behave as expected. To fix this, use:The goal
variant2(f('$VAR'(0),_),f(_,'$VAR'(0)))
should fail but succeeds. Clearly,variant2/2
assumes that no'$VAR'/1
occur in its arguments.ISO/IEC 13211-1:1995 defines variants as follows:
Note that the
Xs
above is not a variable name but rather (X
)s
. Sos
is here a bijection, which is a special case of a substitution.Here, all examples refer to typical usages in
bagof/3
andsetof/3
where variables happen to be always disjoint, but the more subtle case is when there are common variables.In logic programming, the usual definition is rather:
In other words, they are variants if both match each other. However, the notion of matching is pretty alien to Prolog programmers, that is, the notion of matching as used in formal logic. Here is a case which lets many Prolog programmers panic:
Consider
f(X)
andf(g(X))
. Doesf(g(X))
matchf(X)
or not? Many Prolog programmers will now shrug their shoulders and mumble something about the occurs-check. But this is entirely unrelated to the occurs-check. They match, yes, becauseNote that this substitution replaces all
X
and substitutes them forg(X)
. How can this happen? In fact, it cannot happen with Prolog's typical term representation as a graph in memory. In Prolog the nodeX
is a real address somehow in memory, and you cannot do such an operation at all. But in logic things are on an entirely textual level. It's just likeexcept that one can also replace variables simultaneously. Think of
{ X ↦ Y, Y ↦ X}
. They have to be replaced at once, otherwisef(X,Y)
would shrink intof(X,X)
orf(Y,Y)
.So this definition, while formally perfect, relies on notions that have no direct correspondence in Prolog systems.
Similar problems happen when one-sided unification is considered which is not matching, but the common case between unification and matching.
According to ISO/IEC 13211-1:1995 Cor.2:2012 (draft):
For your definition of
variant1/2
,subsumes_term(f(X,Y),f(Y,X))
already fails.