两个变量列表的相等性

时间:2015-01-13 17:16:07

标签: prolog iso-prolog

如果两个唯一变量列表使用当前ISO标准中的the built-ins包含完全相同的变量,那么如何定义测试(因此成功或失败)的元逻辑谓词(ISO / IEC 13211-1: 1995年包括Cor.2)。

换句话说,如果一个唯一变量列表是另一个变量的排列,则谓词应该成功。与library(ordsets)类似,让我们称之为元逻辑谓词varset_seteq(As, Bs).

请注意,与ord_seteq/2相比,此谓词不能只是As == Bs

4 个答案:

答案 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;:)的力量。