2012-01-22 22 views
0

我無法理解這一點。假設我有:如何檢查是否有兩個事實代表相同的序言

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

有沒有一種方法可以證明沒有兩個人具有相同的名稱? 我想這樣做:

person(X) = person(Y). 

但是這給:

X = Y 

或是否足夠?

回答

4

上面你正在使用一元關係person/1(代表單個參數)。你定義彼得,鮑勃和阿曼達是人的事實。然後,您要求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. 
0

在序言的邏輯核心,不應該是唯一的和重複規則之間的任何區別; 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. 
0

要做到這一點,最簡單的方法是創建名稱和測試的列表,如果列表中有任何重複。

findall(Name,person(Name),NameList) 

做了第一部分。然後檢查重複項可以很簡單

is_set(NameList) 

如果您使用SWI-prolog,例如。或者在排序前後檢查列表的長度(刪除重複項)。或者對列表進行排序並在列表中檢查列表的相鄰元素是否相同。

相關問題