如何检查prolog中是否存在两个相同的事实

时间:2012-01-22 05:46:19

标签: prolog

我无法理解这一点。假设我有:

person(peter).
person(bob).
person(amanda).

有没有办法可以证明没有两个人有同一个名字? 我试过了:

person(X) = person(Y).

但这给出了:

X = Y

或者这就够了吗?

3 个答案:

答案 0 :(得分:4)

上面你正在使用一元关系person/1(代表单个参数)。你定义peter,bob和amanda是人的事实。然后,您要求Prolog统一person(X)person(Y),即找到XY的最常规值,使表达式成立。当然,我们只需要Y = X就可以回复。

如果你想强制执行这样的条件,你需要用别人的名字来表示别人,否则他们就会隐含地相等。

假设使用id。

person(1).
person(2).
person(3).

name(1, peter).
name(2, bob).
name(3, amanda).

然后查询

?- name(Y, X), name(Z, X), Y \= Z.

答案 1 :(得分:0)

在Prolog的逻辑核心内,独特规则和重复规则之间不应有任何区别; person(peter)是可证明的,或者不是,这是(纯粹的)Prolog可以提出的唯一问题。

但是走出逻辑核心,你可以做更多的事情,比如算术,I / O,以及在运行时将数据库分开。最后一个在这里特别方便,因为这意味着我们可以从数据库中删除规则person(bob).,然后检查它是否仍然是可证明的。

首先,为了使规则可修改,我们需要将仿函数声明为动态:

:- dynamic person/1.
person(peter).
person(bob).
person(amanda).

完成后,我们可以使用retract(person(bob))删除规则,assert(person(bob))将其删除。

现在,如果您不介意删除数据库,只需:

has_duplicates :- person(X), retract(person(X)), person(X).

但我们可能希望按照我们发现的方式保留所有内容,因此我们需要跳过几个环节:

has_duplicates :- person(X), retract(person(X)), assert(backup(X)), person(X), restore.
has_duplicates :- restore, fail.

restore :- backup(X), retract(backup(X)), assert(person(X)), fail.
restore :- true.

答案 2 :(得分:0)

最简单的方法是创建名称列表并测试列表是否有重复项。

findall(Name,person(Name),NameList)

是第一部分。然后检查重复项可以像

一样简单
is_set(NameList)

例如,如果您使用SWI-prolog。或者在排序之前和之后检查列表的长度(删除重复项)。或者对列表进行排序并向下运行列表,检查列表的相邻元素是否相同。