【问题标题】:Prolog - SubsetProlog - 子集
【发布时间】:2014-11-22 22:25:52
【问题描述】:

我对 Prolog 有点陌生。我正在尝试编写一个函数子集(Set,Subset)来确定 Subset 是否是 Set 的子集(duh)。此外,如果第二个参数没有实例化,它应该输出每个可能的子集。现在,它在两个参数都被实例化时工作,但是当我试图输出所有子集时,它遇到了 member/2 的问题。例如:

?- subset([1,2,3], S).
S = [];
S = [1];
S = [1, 1];
S = [1, 1, 1];
...

这是我的代码:

% subset/2
% subset(Set, Subset) iff Subset is a subset of Set
subset(_, []).
subset(Set, [H|T]) :-
  member(H, Set),
  subset(Set, T).

如何让成员不会一直选择 Set 中的第一个选项?

【问题讨论】:

  • "(duh)": 有这样一个名字很令人困惑:考虑set_subset(Set, Subset)
  • 请注意,您评论中的iff 并不准确,因为Set = any, Subset = [] 等等。相反,简单地说if
  • Subsets in Prolog的可能重复

标签: prolog


【解决方案1】:

(包括 SICStus 和 SWI 在内的许多 Prolog 系统在它们的库中都有一个 subset/2,而是 subset(Subset, Set) ;而且它也不是一个干净的关系......)

这完全取决于你所说的集合是什么意思。 [1, 1] 是有效集合吗?它们必须以一种顺序或另一种顺序发生吗?如果您允许重复,您的定义很好。毕竟你的定义是:

set_subset(Set, Subset)Subset的所有元素都是Set的元素

令您颇为惊讶的是,您现在有无限的解决方案。而且,更糟糕的是,该集合以非常不公平的方式列举。如果您担心的只是列举了精确的顺序解决方案,请考虑:

?- length(Subset,N), set_subset([1,2,3], Subset).
Subset = [], N = 0 ;
Subset = [1], N = 1 ;
Subset = [2], N = 1 ;
Subset = [3], N = 1 ;
Subset = [1, 1], N = 2 ;
Subset = [1, 2], N = 2 ;
Subset = [1, 3], N = 2 ;
Subset = [2, 1], N = 2 ;
Subset = [2, 2], N = 2 ;
Subset = [2, 3], N = 2 ...

如果您希望Subset 具有有限多个解决方案,您可能需要一个子序列。见this answer

【讨论】:

  • @j4nbur53:请注意最后一句话!
  • @j4nbur53:请重读我的回答:这是关于 OP 的解决方案!
  • @j4nbur53:OP 问道:“基本上,我如何才能让成员不会一直选择 Set 中的第一个选项?”
  • @j4nbur53:对不起,我在回答中解决了这个问题。而且它与不必要的选择点无关,它只是一组解决方案的基数。
【解决方案2】:

要枚举子集,我认为没有必要也生成排列,毕竟集合不应该关心排序。所以典型的text book解决方案是:

% subset(-Set, +Set)
subset([X|L], [X|R]) :-
   subset(L, R).
subset(L, [_|R]) :-
   subset(L, R).
subset([], []).

将此与其他解决方案进行比较:

这个解决方案:

?- subset(X, [1,2,3]), write(X), nl, fail; true.
[1,2,3]
[1,2]
[1,3]
[1]
[2,3]
[2]
[3]
[]

其他capellis解决方案:

?- subset([1,2,3], X), write(X), nl, fail; true.
[]
[1]
[1,2]
[1,2,3]
[1,3]
[1,3,2]
[2]
[2,1]
[2,1,3]
[2,3]
[2,3,1]
[3]
[3,1]
[3,1,2]
[3,2]
[3,2,1]

从集合论我们知道 |P(A)|=2^|A|,所以对于 3 元素长的输入子集应该生成 8 个子集。这就是这个解决方案所做的,但其他解决方案列举了许多冗余子集的方式。

【讨论】:

  • 您正在给出具有反向参数的子序列的定义。这再次包括许多冗余解决方案,如subset(X, [a,a,a])
  • Prolog 中也没有多重集,即。 [1,2][2,1].
  • 如果你想要非冗余的解决方案,你需要调用sort([a,a,a], Y), subset(X, Y),subset/2 谓词不会以任何方式改变。 sort/2 是 ISO 核心标准的一部分。
  • 在 Jekejeke Prolog 中代替 sort/2,您也可以使用 sys_distinct/2。此谓词尝试保留输入顺序,并删除重复项。另见:github.com/jburse/jekejeke-devel/blob/master/jekrun/headless/…
猜你喜欢
  • 2011-06-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多