我無法理解這一點。假設我有:如何檢查是否有兩個事實代表相同的序言
person(peter).
person(bob).
person(amanda).
有沒有一種方法可以證明沒有兩個人具有相同的名稱? 我想這樣做:
person(X) = person(Y).
但是這給:
X = Y
或是否足夠?
我無法理解這一點。假設我有:如何檢查是否有兩個事實代表相同的序言
person(peter).
person(bob).
person(amanda).
有沒有一種方法可以證明沒有兩個人具有相同的名稱? 我想這樣做:
person(X) = person(Y).
但是這給:
X = Y
或是否足夠?
上面你正在使用一元關係person/1
(代表單個參數)。你定義彼得,鮑勃和阿曼達是人的事實。然後,您要求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.
在序言的邏輯核心,不應該是唯一的和重複規則之間的任何區別; 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.
要做到這一點,最簡單的方法是創建名稱和測試的列表,如果列表中有任何重複。
findall(Name,person(Name),NameList)
做了第一部分。然後檢查重複項可以很簡單
is_set(NameList)
如果您使用SWI-prolog,例如。或者在排序前後檢查列表的長度(刪除重複項)。或者對列表進行排序並在列表中檢查列表的相鄰元素是否相同。