List Prolog程序,用于查找任意顺序的两个列表的相等性
我想写一个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
没关系。所以我写了以下内容:
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
- 同时确保片段不会以上述目标终止
- 要使目标
普遍终止相等([1,2,3],X)
- 。。。我们必须更改至少一个剩余部分(未划破的部分)李>
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).