如果两个唯一变量列表使用当前ISO标准中的the built-ins包含完全相同的变量,那么如何定义测试(因此成功或失败)的元逻辑谓词(ISO / IEC 13211-1: 1995年包括Cor.2)。
换句话说,如果一个唯一变量列表是另一个变量的排列,则谓词应该成功。与library(ordsets)
类似,让我们称之为元逻辑谓词varset_seteq(As, Bs).
请注意,与ord_seteq/2
相比,此谓词不能只是As == Bs
。
答案 0 :(得分:14)
我建议的解决方案使用term_variables/2
检查Bs
是否没有As
以外的额外变量,As
没有Bs
中没有出现的变量}}
varset_seteq(As, Bs):-
term_variables(As-Bs, As),
term_variables(Bs-As, Bs).
上述解决方案可以通过不是自由变量集的参数来成功:
| ?- varset_seteq([A], [a]).
A = a
yes
为避免这种情况,可以用等价测试代替统一:
varset_seteq(As, Bs):-
term_variables(As-Bs, A0),
A0 == As,
term_variables(Bs-As, B0),
B0 == Bs.
答案 1 :(得分:7)
如果我们假设这两个列表包含唯一变量,则以下使用双重否定有效:
varset_seteq(As, Bs) :-
\+ \+ (numbered_from(As, 1),
sort(Bs, SBs),
As == SBs).
numbered_from([], _).
numbered_from([X|Xs], X) :-
X1 is X + 1,
numbered_from(Xs, X1).
这与Paulo的解决方案类似,但避免了ISO / IEC 13211-1仅在sort/2
的单次执行中要求变量排序的问题。
答案 2 :(得分:4)
另一种解决方案,<强>少效率高于Tudor的聪明解决方案,因而不推荐,但仍然值得一提,因为我看到它在多个场合使用,是:
varset_seteq(As, Bs) :-
sort(As, Sa), sort(Bs, Sb), Sa == Sb.
答案 3 :(得分:3)
另一种方法。如果我们为自己提供这些高阶谓词(它们各自有用),
select_with(_, _, [], []).
select_with(P, X, [Y|Ys], Ys) :- call(P, X, Y), !.
select_with(P, X, [Y|Ys], [Y|Ks]) :-
select_with(P, X, Ys, Ks).
foldl(_,[],Vn,Vn).
foldl(P,[X|Xs],V0,Vn) :-
call(P,X,V0,V1),
foldl_(P,Xs,V1,Vn).
然后我们可以轻松定义一个谓词,如果每个成员一个列表在另一个列表中具有相等的元素(使用==/2
),则该谓词为:
members_equal(A, B :-
foldl(select_with(==), A, B, []).
如果我们验证传入的参数是varsets,那么这个谓词可以专门用于声明的目的。以下是我能够在这个方向上提出的最佳方案(但它会吃掉相当多的推论):
is_varset([]).
is_varset([V|Vs]) :-
var(V),
maplist(\==(V), Vs),
is_varset(Vs).
(至少在SWI Prolog上,使用sort/2
比上面的推论更少。推测这是因为排序是用C完成的。另外,这个答案仍然没有接近{的优雅{1}}方法 - 这是&#34;语义上升&#34;:)的力量。