List Prolog中的子列表(不识别空列表) < P>我想在Prolog中创建一个谓词,它将检查列表A是否是列表B的子列表。此外,我不希望我的程序将空列表视为另一个列表的子集。

List Prolog中的子列表(不识别空列表) < P>我想在Prolog中创建一个谓词,它将检查列表A是否是列表B的子列表。此外,我不希望我的程序将空列表视为另一个列表的子集。,list,prolog,meta-predicate,List,Prolog,Meta Predicate,例如,列入清单([1,4],[1,2,3,4,5])。 对。 列入清单([2,3],[1,2,3,4,5])。 对。 列入清单([1,6],[1,2,3,4,5])。 错。 包括的清单([],[1,2,3,4,5])。 错。 等等 到目前为止,我已经编写了以下代码: member(X,[X|Tail]). member(X,[Head|Tail]):- member(X,Tail). included_list([X],_). included_list([Head|Tail],List):-

例如,列入清单([1,4],[1,2,3,4,5])。 对。 列入清单([2,3],[1,2,3,4,5])。 对。 列入清单([1,6],[1,2,3,4,5])。 错。 包括的清单([],[1,2,3,4,5])。 错。 等等

到目前为止,我已经编写了以下代码:

member(X,[X|Tail]).
member(X,[Head|Tail]):- member(X,Tail).

included_list([X],_).
included_list([Head|Tail],List):- member(Head,List), included_list(Tail,List).
但是上面的代码似乎是错误的,因为在一个特定的情况下,它抛出true,而不是抛出false。我希望在展示了以下屏幕截图后能够清楚地说明这一点:

正如你可能已经注意到的,第五(5)句给出的是真的,而不是错的。也就是说,当我写一个句子的形式:

包括的列表([x,y],[w,x,v,z])

然而,第二个列表中只包含了x(而不是y),程序给了我true(这是错误的)

一般来说,如果第一个列表的第一个参数包含在第二个列表中,那么无论前一个列表的其余部分是否包含在后一个列表中,程序都会给出true

在任何其他情况下,程序都会给出正确的结果(正确或错误)

我做错了什么

我会等待你的回答


提前谢谢你

您的问题是
包含列表/2
的第一条。这:

included_list([X], _).
这是什么意思?它的意思是,“如果第一个参数是一个包含一个元素的列表,则成功,忽略第二个参数。”

旁白:如果您不忽略编译器警告,那么您可能已经发现了这个错误。您应该得到一个响亮而清晰的“Singleton variable”警告,提示您编写的代码没有达到您认为的效果

你真正的意思是:

subset_list([X|Xs], Ys) :-
    subset_list_1(Xs, X, Ys).

subset_list_1([], X, Ys) :-
    member(X, Ys).
subset_list_1([X|Xs], X0, Ys) :-
    member(X0, Ys),
    subset_list_1(Xs, X, Ys).
但我不知道为什么您不简单地使用可用的,并简单地添加一个要求,即子集不是空列表:

subset_list(Subset, List) :-
    Subset = [_|_], % a list with at least one element
    subset(Subset, List).
尽管文档声称,
subset/2
的第二个参数不必是真正的“集合”,但它确实希望两个列表都是基础(不包含任何自由变量)。您可以看到源代码。

在这个答案中,我们将处理递归并定义:

all_included(Sub, Es) :- same_length(Es, Xs), Sub = [_|_], % minimum length: 1 append(_, Sub, Xs), % maximum length: as long as `Es` maplist(list_member(Es), Sub). 接下来,一些我们预期会失败的用例:

?- member(Xs, [[],[2,6],[1,6]]), all_included(Xs, [1,2,3,4,5]).
false.

?- all_included([3,5], [1,2,5]).
false.

member/2
是ISO,因此您无需自行定义。Prolog抛出异常,不是真的或“错的”。首先,基本情况是有缺陷的!您的意思是
included\u list/2
对于任何一个项目列表都是正确的。相反,如果说
included\u list([],\u)
,它就会工作得很好。我倾向于用
forall(member(X,Subset),member(X,list))
来解决它,但我很恼火它没有生成@DanielLyons这就是findall的作用
forall
是用来产生副作用的,它不创建绑定是出于设计。@Boris谢谢!OTOH我很难用
findall/3
找到正确的公式。你知道怎么做吗?
?- member(Xs, [[],[2,6],[1,6]]), all_included(Xs, [1,2,3,4,5]).
false.

?- all_included([3,5], [1,2,5]).
false.