2013-12-16 45 views
1

時跳過一些事實我有一個表示向圖下列知識庫:的Prolog - 迭代

edge(1, 2). 
edge(2, 3). 
edge(2, 4). 
edge(3, 3). 
edge(3, 4). 
edge(3, 5). 
edge(4, 3). 

我想打印爲每個節點傳入和傳出邊緣的數量之間的差異。這是我到目前爲止:

outgoing(E) :- edge(E, _). 
ingoing(E) :- edge(_, E). 

count_outgoing(E, Count) :- findall(E, outgoing(E), Bag), length(Bag, Count). 
count_ingoing(E, Count) :- findall(E, ingoing(E), Bag), length(Bag, Count). 

count(E, D) :- count_outgoing(E, OC), count_ingoing(E, IC), D is IC - OC. 

count :- edge(E, _), count(E, D), write(E), write(' '), write(D), nl, fail; true. 

但是,此解決方案重複具有多個傳出邊緣的節點。我該如何解決它? (讓我們跳過一個事實,即如果一個節點沒有任何外出邊緣,它現在不會被打印)。

回答

1

問題是count_outgoing/2count_incoming/2隱式地找到您的節點。如果你明確地做了,你就可以擁有你需要的控制。最簡單的方法是獲取一組節點並迭代它。就像這樣:

node(N) :- edge(N, _) ; edge(_, N). 
all_nodes(Nodes) :- setof(N, node(N), Nodes). 

你的主要然後可以使用member/2生成節點:

count :- 
    all_nodes(Nodes), 
    forall(member(N, Nodes), 
    (count(N, D), 
    format('node ~a has a difference of ~a~n', [N, D]))).