2014-12-02 35 views
2

週期我定義爲用戶的事實清單:序言:消除間接關係

user(@michael). 
user(@ana). 
user(@bob). 
user(@george). 
user(@john). 

等。此外,我還有一組事實爲:

follows(@michael,@ana). 
follows(@ana,@bob). 
follows(@bob,@michael). 

我想寫的關係是間接的(用戶1,用戶1),這將告訴我,如果USER1間接如下user2的。 但是,我無法消除循環關係。

就像在給出的例子中,michael - > ana - > bob - > michael會引起一個循環。

從間接(user1,user2)的結果中消除這些循環的最佳方法是什麼?

+1

爲什麼你用'@'作爲前綴名? – false 2014-12-02 22:16:27

+0

@false,我正在嘗試使用prolog創建twitter,並且給出的規則之一是用戶名以@開頭。 – na899 2014-12-03 04:16:31

+0

嘗試'write_canonical(@abx).'它給出'@(abx)'。也就是說,'@'是一個前綴運算符(SWI)。如果你真的想在名字中用@寫''@ name'' – false 2014-12-03 09:18:29

回答

1

您可以制定一條規則,傳遞您迄今爲止「已見過」的用戶的額外列表,並忽略來自這些用戶的以下內容:follows(A, B, Seen)

要做到這一點,定義一個包裝實際規則「跟隨傳遞」的規則,就像這樣:

follows_tx(A, B) :- follows(A, B, []). 

現在,您可以定義follows/3規則是這樣的:

follows(A, B, Seen) :- 
    not_member(B, Seen), 
    follows(A, B). 
follows(A, B, Seen) :- 
    follows(A, X), 
    not_member(X, Seen), 
    follows(X, B, [A|Seen]). 

基地條款說如果在B之後有一個關於A的事實,只要我們之前沒有看到B,我們就會考慮謂詞。

否則,我們找到誰如下A,檢查我們還沒有通過檢查not_member/2看出,用戶還沒有,終於看到如果用戶跟隨B,直接或間接地。

最後,這裏是你如何定義not_member

not_member(_, []). 
not_member(X, [H|T]) :- dif(X, H), not_member(X, T). 

Demo.

+0

現在,'以下(A,B)'只有三種解決方案。這就是爲什麼'not_member/2'中的'(\ =)/ 2'不是一個好主意。 – false 2014-12-02 23:59:58

+0

感謝您的幫助@dasblinkenlight。 – na899 2014-12-03 04:14:08

+0

@ na899不客氣!看看最後一次編輯的錯誤(用'dif/2'替換'= \')。 – dasblinkenlight 2014-12-03 04:17:15