2010-11-16 89 views
6

我正在學習prolog,並正在閱讀一本名爲Programming Prolog for a Artificial Intelligence的書。作爲練習,我想學習如何擴展本書中的一個例子。有人可以幫忙嗎?在Prolog中獲取解決方案列表

假設你有這些事實:

parent(pam, bob). %pam is a parent of bob 
parent(george, bob). %george is a parent of bob 

我怎麼會寫序言謂詞會給我父母鮑勃的名單?例如:

list_parents(bob, L). 

L = [pam, george] ; 
L = [george, pam] ; 
true. 

回答

2

試試這個:

parent(pam, bob). %pam is a parent of bob 
parent(george, bob). %george is a parent of bob 
list_parents(A, Es, [X|Xs]) :- parent(X, A), \+ member(X, Es), list_parents(A, [X|Es], Xs). 
list_parents(A, Es, []). 

這是一個低效的方法,更好的方法將需要一個「解決方案」較高階謂詞。

list_parents(X,YS): - 解決方案(父母,[X,W],1,YS)

+1

我貼的後續問題你的回答就「解決方案」謂:https://stackoverflow.com/questions/47233986/higher-order-解決方案 - 謂詞 – mrsteve 2017-11-11 03:44:57

12

的所有解決方案謂語像findall/3可能做的伎倆:

list_parents(P, L) :- 
    findall(Parent, parent(Parent, P), L). 

簡單put findall/3找到Parent在'backtrack-able'目標parent(Parent, P)中的所有綁定,並將Parent的所有綁定放入列表L。請注意,這不會刪除重複項,但您可以在將它返回到創建集之前執行sort/2L。執行此:

?- list_parents(bob, L). 
L = [pam, george]. 

如果沒有findall/3在PROLOG實現呢,你可以手工做這樣的:

list_parents(P, L) :- 
    list_parents(P, [], L). 

list_parents(P, Acc, L) :- 
    parent(Parent, P), 
    \+ member(Parent, Acc), !, 
    list_parents(P, [Parent|Acc], L). 
list_parents(_, L, L). 

這個版本發送到list_parents/2接聽的儲液器的版本, list_parents/3。後者試圖收集Parent綁定,只要我們之前沒有看到它們(因此\+ member檢查),並且返回沒有找到新的Parent綁定到Acc列表中的列表。執行這給了我們同樣的結果作爲第一個選項:

?- list_parents(bob, L). 
L = [pam, george]. 
+1

'findall',這就是我試圖Google爲 – 2010-11-18 01:38:08

+0

sharky,你findall實現不佔重複元素。如果你在數據庫中有這個: 'parent(hannah,carl)。父母(hannah,carl) 。父母(鮑勃,卡爾)。 你的規則輸出[hannah,bob]。但是,如果你嘗試findall你得到[hannah,hannah,bob] – 2016-01-31 17:28:56