我无法理解这一点。假设我有:
person(peter).
person(bob).
person(amanda).
有没有办法可以证明没有两个人有同一个名字? 我试过了:
person(X) = person(Y).
但这给出了:
X = Y
或者这就够了吗?
答案 0 :(得分:4)
上面你正在使用一元关系person/1
(代表单个参数)。你定义peter,bob和amanda是人的事实。然后,您要求Prolog统一person(X)
和person(Y)
,即找到X
和Y
的最常规值,使表达式成立。当然,我们只需要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。或者在排序之前和之后检查列表的长度(删除重复项)。或者对列表进行排序并向下运行列表,检查列表的相邻元素是否相同。