检查孩子是否在Prolog中至少有3个父母

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了检查孩子是否在Prolog中至少有3个父母相关的知识,希望对你有一定的参考价值。

我试图解决一个问题,你会得到一个事实列表,如:

parent(a,b).

其中ba的父母,我需要写一个条款来确定某人是否至少有3个父母。

这是我的尝试

has3Parent(A) :- parent(A,B), parent(A,C), parent(A,D).

我的尝试,

如果A有1个父母,它将返回true一次,

如果A有2个父母,它将返回真实的8次,

如果A有3个父母,它将返回真实27次。

我对Prolog很新,我无法理解为什么会这样,所以任何帮助都会非常感激。

答案

因为你从来没有保证BCD是不同的人,只要true甚至有一个A,你将永远得到parent

所以1 parent的情况很简单; 2,你有这八种组合:

A = jane, B = jane, C = jane
A = jane, B = jane, C = john
A = jane, B = john, C = jane
A = jane, B = john, C = john
A = john, B = jane, C = jane
A = john, B = jane, C = john
A = john, B = john, C = jane
A = john, B = john, C = john

即使你只是说他们不平等,你也会因为少于3而得到假,而对于3或更多则是假的。但你仍然会得到多种解决方案,因为秩序很重要。

理想情况下,你会使用findall/3获取父母的数量并计算它,这将给你一个独特的解决方案。就像是:

has3Parent(A) :- findall(P, parent(A, P), Ps), length(Ps, 3).

(另请注意,与之前的不同,这测试A是否有3个父母,而不是至少3个父母。为了让前面的想法测试正好3个父母,你不得不说除了BCD之外不同,也不存在E不同于所有这些也是parent。虽然findall解决方案很容易适应不同类型的比较,因为你正在处理一个数字,而不是一堆不守规矩的变量。)

另一答案

首先是一个小问题:你使用的关系parent/2parent(Child, Parent)这样的参数。有许多人使用这个名称与交换的参数,因此parent(Parent, Child)。因此,在名称中直接说明您想要的订单会更安全。因此,child_parent(Child, Parent)是一个更好的名称,或短的child_of(Child, Parent)

每当您尝试定义谓词时,首先要考虑当谓词依赖于更改时该谓词的行为方式。在你的情况下,如果将更多事实添加到child_of/2会发生什么?

你最初要求至少有3个父母,让我们称之为has3parentsminimum/1这种关系。然后定义正好3个父母has3parents/1然后@Amadan的definition has3parentsA/1

让我们在向child_of/2添加事实之前和之后比较一组解决方案。

has3parentsminimum/1:这套解决方案增加或保持不变。如果另一个孩子现在有3个或更多父母,它会增加。

has3parents/1:解决方案集可能增加或减少,或两者兼而有之(因此只是改变)。因为有些孩子现在可能有四个或更多的父母,而其他孩子现在有三个。

has3parentsA/1:与has3parents/1一样,但另外,如果添加冗余事实,解决方案集也可能会发生变化。

所以has3parentsminimum/1在添加更多事实时非常稳定。这被称为单调性:在添加新条款时,您知道的所有内容在真实之前都是真实的。尽可能长时间地保持Prolog的单调子集是一个非常好的主意,因为在这个部分你可以学到很多关于关系的知识。 (这可能就是你练习这个练习的原因。)

has3parentsminimum/1最自然的定义是使用dif/2

has3parentsminimum(Ch) :-
   dif(P1,P2), dif(P1,P3), dif(P2, P3),  % all parents are different
   child_of(Ch, P1),
   child_of(Ch, P2),
   child_of(Ch, P3).

这可能是你需要去的地方。是的,你会得到3! = 6个多余的解决方案,每个孩子只有三个父母,对于3个以上父母的孩子更是如此,但这套解决方案很好。

但是还有进一步的改进(以一定的价格得到)。如果child_of/2仅包含基本事实,您可以写:

has3parentsminimum(Ch) :-
   setof(P, child_of(Ch, P), [_,_,_|_]).

以上是关于检查孩子是否在Prolog中至少有3个父母的主要内容,如果未能解决你的问题,请参考以下文章

孩子不跟随父母

选中/取消选中父母和孩子

查找文本文件中至少有两个共同单词的所有行(Bash)

Prolog二叉搜索树测试 - 不需要的父母的父节点比较

父母杀死孩子后,孩子的Linux /proc/PID dir仍然活着

IllegalStateException,指定的孩子已经有一个父母 - ListFragment