Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
真子集-Prolog_Prolog_Subset - Fatal编程技术网

真子集-Prolog

真子集-Prolog,prolog,subset,Prolog,Subset,我正试图编写一个程序,将两个列表作为输入,并检查适当的子集。我从以下几点开始: proper([A],[]). proper([],[A]). proper([A|T1],[A|T2]) :- proper(T1,T2). 对于顺序完全相同的输入,这种方法非常有效。例如: ?- proper([a,b,c],[a,b,c,d]). Yes 但不适用于以下输入: ?- proper([a,b,c],[b,d,a,c]). No 在浏览网站后,我发现了之前提出的问题: 这导致我修改代码如下:

我正试图编写一个程序,将两个列表作为输入,并检查适当的子集。我从以下几点开始:

proper([A],[]).
proper([],[A]).
proper([A|T1],[A|T2]) :- proper(T1,T2).
对于顺序完全相同的输入,这种方法非常有效。例如:

?- proper([a,b,c],[a,b,c,d]).
Yes
但不适用于以下输入:

?- proper([a,b,c],[b,d,a,c]).
No
在浏览网站后,我发现了之前提出的问题:

这导致我修改代码如下:

proper([A],[]).
proper([],[A]).
proper([A|T1],[A|T2) :- member(A,T2), proper(T1,T2).
proper([H1|T1], [H2|T2]) :- \+ member(H1, T2).
这适用于子集,但不适用于适当的子集。我认为我的问题是因为我理解property/4的第二条是如何工作的。非常感谢您的任何帮助

编辑:

意识到我试图确定第一个列表是否是第二个列表的适当子集,第二个列表是否是第一个列表的适当子集。将代码清理得更精确

proper([],_).
proper([A|T1],[A|T2) :- member(A,T2), proper(T1,T2).
proper([H1|T1], [H2|T2]) :- \+ member(H1, T2).

如果我理解正确,您上次尝试中的前两个声明将意味着,包含1个元素的列表是空列表的适当子集(false),而空列表是包含一个元素的列表的适当子集(true);第一个应该是有问题的,因为
property([1],])
property([],[1])
都会成功,但是property子集关系是不对称的

我相信您第二次尝试没有过滤出相同子集的原因是您没有要求A小于B的声明

以下是我提出的一些可能的解决方案。为了提高清晰度和简洁性,我使用了两次
较小的设置/2

smaller_set(A, B) :-
    length(A, LA),
    length(B, LB),
    LA < LB.
一个递归定义的示例,基于移除A和B的每个匹配元素。它确保A
rec_proper_subset1([], [_|_]).
rec_proper_subset1([_e|A], B) :-
    select(_e, B, C),            % C is B with _e removed. Only true if _e is in B.
    rec_proper_subset1(A, C).
一旦主谓词已经确定A
rec_proper_subset2(A, B) :-
    smaller_set(A, B),
    rec_proper_subset2_(A, B).

rec_proper_subset2_([], _).
rec_proper_subset2_([_e|A], B) :-
    member(_e, B),
    rec_proper_subset2_(A, B).
编辑:

  • 如果要确保列表中没有任何重复元素,则需要使用
    list\u\u-to\u-set/2
    sort/2
    ,或类似的方法。但这类解决方案也可以用于查找子列表
  • 我认为
    def_property_subset/2
    是一种蹩脚的解决方案,因为它只能检查a是B的子集,但不能在a中生成B的子集。另外两个可以思考

(我搞砸了,忘了包括
rec_property\u subset2/2
的基本定义,但我现在已经修复了它)。

只需对列表进行排序即可。这是最明智的做法,也是标准库处理它的方式。@Boris你能告诉我正确子集的标准库谓词吗?@aBathologist看一看库(ordsets)(例如在SWI Prolog实现中)及其源代码。“适当”子集没有谓词,但正如您在回答中所指出的那样,只看长度就足够了。@a语法学家我的观点主要是,当“集合”的概念表示为Prolog列表时,处理它的唯一明智的方法是保持列表的排序。列表是嵌套的术语,只能在一个方向上遍历。@Boris我明白了!这是一个重要的观点。我只是觉得我忽略了一个库,或者有一种特殊的方法可以使用sort来完成正确的子集检查,我无法完全理解。谢谢你的详细阐述。是的,在对它进行了更多的研究之后,我意识到我正在尝试检查A是否是B的适当子集,反之亦然。我对代码进行了编辑,使其更清晰、更精确。@Shrp91供参考:我的部分答案出错,现在已更正错误。我最终使用select/3功能使其正常工作。非常感谢你的回答。
rec_proper_subset2(A, B) :-
    smaller_set(A, B),
    rec_proper_subset2_(A, B).

rec_proper_subset2_([], _).
rec_proper_subset2_([_e|A], B) :-
    member(_e, B),
    rec_proper_subset2_(A, B).