Prolog比较列表结构

时间:2013-12-20 21:02:45

标签: list prolog

我试图在prolog中比较两个列表,如

?- compare([[X],Y,Z],[[A],B,C]).
true.
?- compare([X,Y,Z],[[A],B,C]).
false.

我不能使用== / 2运算符,因为逻辑变量不一样, 所以这会对两种情况都评估为假。 我显然不能使用= / 2,因为在两种情况下都会评估为真。

有关如何解决此问题的任何建议?

5 个答案:

答案 0 :(得分:4)

检查两个术语是否具有相同结构的替代解决方案是使用ISO Prolog标准谓词subsumes_term/2。当术语是另一个术语的变体时,以下谓词variant/2为真:

variant(Term1, Term2) :-
    \+ \+ subsumes_term(Term1, Term2),
    \+ \+ subsumes_term(Term2, Term1).

使用双重否定避免实例化参数中的任何变量。使用例如用于测试的GNU Prolog:

| ?- variant([[X],Y,Z],[[A],B,C]).

(1 ms) yes
| ?- variant([X,Y,Z],[[A],B,C]).

no

答案 1 :(得分:1)

如果您只是想匹配列表结构,可能是这样的:

compare([H1|T1], [H2|T2]) :-
    is_list(H1),
    is_list(H2),
    compare(H1, H2),
    compare(T1, T2).
compare([H1|T1], [H2|T2]) :-
    \+ is_list(H1),
    \+ is_list(H2),
    compare(T1, T2).
compare([], []).

| ?- compare([[X],Y,Z],[[A],B,C]).

true ? ;

no
| ?- compare([X,Y,Z],[[A],B,C]).

no

这个解决方案的优点在于,无论变量是否被实例化,它都将起作用。

| ?- compare([[a],b,c], [[d],X,f]).

true ? ;

no
| ?-

答案 2 :(得分:1)

这适用于所提供的测试用例

elemcmp(A,B) :- var(A), var(B), ! ; A =@= B.

?- maplist(elemcmp,[[X],Y,Z],[[A],B,C]).
true.

?- maplist(elemcmp,[X,Y,Z],[[A],B,C]).
false.

答案 3 :(得分:1)

您可以使用(SWI Prolog,至少),=@=/2。像Term1 =@= Term2这样的测试是真的

  

如果Term1是(或结构上等同于)Term2的变体。   对变体的测试弱于等价(== / 2),   但比统一更强(= / 2)。   两个术语AB是变体iff [ sic ]存在变量的重命名   在A中,A等效(==)到B,反之亦然。

基本上,foo(A,B)foo(B,C)以及foo(C,D)是彼此的变体,而不是foo(A,A)的变体。

针对匿名变量的测试表现如您所料:foo(_,_)foo(A,B)的变体,但不是foo(A,A)的变体(因为匿名变量的所有用法都是不同的)。

答案 4 :(得分:0)

这是另一种解决方案:

compare(A, B) :- (var(A); var(B)), !, var(A), var(B).
compare([], []).
compare([H1|T1], [H2|T2]) :- compare(H1, H2), compare(T1, T2).

要接受原子,请使用\+ is_list(...)或等效代替var(...)