List Prolog程序,用于查找任意顺序的两个列表的相等性

List Prolog程序,用于查找任意顺序的两个列表的相等性,list,prolog,any,failure-slice,program-slicing,List,Prolog,Any,Failure Slice,Program Slicing,我想写一个Prolog程序来找出两个列表的相等性,其中元素的顺序 没关系。所以我写了以下内容: del(_, [], []) . del(X, [X|T], T). del(X, [H|T], [H|T1]) :- X \= H, del(X, T, T1). member(X, [X|_]). member(X, [_|T]) :- member(X, T). equal([], []). equal([X], [X]). equal([H1|T], L

我想写一个Prolog程序来找出两个列表的相等性,其中元素的顺序
没关系。所以我写了以下内容:

del(_, [], []) .
del(X, [X|T], T).  
del(X, [H|T], [H|T1]) :-
   X \= H,
   del(X, T, T1).

member(X, [X|_]).  
member(X, [_|T]) :- 
   member(X, T).

equal([], []).  
equal([X], [X]).  
equal([H1|T], L2) :-
   member(H1, L2),
   del(H1, L2, L3),
   equal(T, L3).  
但是当我输入像
equal([1,2,3],X])
,它不会显示
X
的所有可能值。相反,程序挂在中间。原因可能是什么?

试试这个:

isSubset([],_).
isSubset([H|T],Y):-
    member(H,Y),
    select(H,Y,Z),
    isSubset(T,Z).
equal(X,Y):-
    isSubset(X,Y),
    isSubset(Y,X).
equal([],[]).
equal([Ha|Ta],[Hb|Tb]) :-
   Ha = Hb, lequal(Ta,Tb).

尝试使用谓词检查其中一个集合是否是另一个集合的置换:

delete(X, [X|T], T).

delete(X, [H|T], [H|S]):-
    delete(X, T, S).


permutation([], []).

permutation([H|T], R):-
    permutation(T, X), delete(H, R, X).
(谓词取自)


我建议使用内置谓词
msort/2
,然后比较列表。在SWI Prolog上需要O(nlogn)时间,而逐个元素检查未排序的列表则需要O(n2)时间

在这里,排序列表需要O(nlog)时间,而在SWI-Prolog上比较它们需要O(n)时间,我不知道其他实现。

简单地说

equal([],[]).
equal([H|T],[H|T1]):-equal(T,T1).
那么:

equal(X, Y) :-
    subtract(X, Y, []),
    subtract(Y, X, []).

如果您不关心列表元素的多重性, 使用检查是否有足够的实例化 , 强制执行 , 并使用类似的方法消除重复项:

使用SWI Prolog 8.0.0的示例:

?- same_elements([a,c,c,b,a,c], [c,b,b,a]). true. ?- same_elements([a,b,b,a], [b,a,b,e]). false. ?- same_elements([a,b,b,a], Xs). ERROR: Arguments are not sufficiently instantiated -相同的元素([a,c,c,b,a,c],[c,b,b,a])。 对。 -相同的元素([a,b,b,a],[b,a,b,e])。 错。 -相同的_元素([a,b,b,a],Xs)。 错误:参数没有充分实例化
您观察到的不终止的实际原因是:以下子句不以任何方式、形状或形式约束
L2

equal([H1|T], L2) :- member(H1, L2), del(H1, L2, L3), equal(T, L3). 相等([H1 | T],L2):- 成员(H1、L2), 德尔(H1、L2、L3), 相等(T,L3)。 因此,您的查询
?-equal([1,2,3],X)。
意味着证明目标
成员(u,L2)
,该成员不是通用终止的。因此,
equal([1,2,3],X)
也不能普遍终止

有关如何解释Prolog代码不终止的更多信息,请阅读


另外,从另一个角度来看终止问题,我们发现,在这种情况下,不终止实际上是一个必要的后果

为什么??因为您不限制多重数的数量,这使得解决方案集的大小是无限的。集合不能由有限数量的答案表示(前提是您不允许延迟目标)。

那么为什么
等于([1,2,3],X)
不能与您的代码通用终止

让我们看一看你的代码!什么是失败片?以下是标签信息:

失败片段是通过添加一些目标
false
获得的Prolog程序片段。故障切片有助于确定纯单调Prolog程序普遍不终止的原因。它们也有助于给出所需推理数量的下限。这是一种具体的技术

要创建故障片,请执行以下操作:

  • 我们在程序中插入
    false
    目标
  • 同时确保片段不会以上述目标终止
del(u,[],[]):-false。 del(X[X | T],T):-假。 del(X,[H|T],[H|T1]):-false, dif(X,H),%注意OP最初使用'X\=H` del(X,T,T1)。 成员(X,[X |)]。 成员(X,[[u124; T]):- 成员(X,T)。 相等([],[]):-false。 相等([X],[X]):-false。 相等([H1 | T],L2):- 成员(H1,L2),错误, 德尔(H1、L2、L3), 相等(T,L3)。 ?-相等([1,2,3],_),假请注意,“false”是多余的。。。 **循环**%。。。如上所述,“相等/2”不能成功。 所以。。。上面的故障片告诉我们什么?它说:

  • 要使目标
    相等([1,2,3],X)
    普遍终止
  • 。。。我们必须更改至少一个剩余部分(未划破的部分)
选择/3之前的成员/2不需要。equal/2不能正常工作:它只给出一个解决方案,然后在重做时挂起:?-equal([1,2,3],X)。X=[1,2,3];错误:由于内存不足,执行中止。因此,投票否决答案。确定两个集合的相等性如果列表包含顺序不同的相同项,则此操作无效。链接已断开。
same_elements(As, Bs) :-
   iwhen(ground(As+Bs), (sort(As,Es),sort(Bs,Es))).
?- same_elements([a,c,c,b,a,c], [c,b,b,a]). true. ?- same_elements([a,b,b,a], [b,a,b,e]). false. ?- same_elements([a,b,b,a], Xs). ERROR: Arguments are not sufficiently instantiated equal([H1|T], L2) :- member(H1, L2), del(H1, L2, L3), equal(T, L3). del(_, [], []) :- false. del(X, [X|T], T) :- false. del(X, [H|T], [H|T1]) :- false, dif(X, H), % note that the OP originally used `X \= H` del(X, T, T1). member(X, [X|_]). member(X, [_|T]) :- member(X, T). equal([], []) :- false. equal([X], [X]) :- false. equal([H1|T], L2) :- member(H1, L2), false, del(H1, L2, L3), equal(T, L3). ?- equal([1,2,3], _), false. % note that `false` is redundant ... ** LOOPS ** % ... as above `equal/2` cannot succeed.