2017-04-23 95 views
1

我剛開始學習有關序言,我徹底困惑。初學者序言:與謂詞邏輯和(也許)語法的問題

請考慮以下情形:我有一個知識庫,其中包含關於一個人的事實,格式爲人(姓名,年齡)。

例子:

person(brad,20). 
person(lindsey,15). 
person(sophie,18). 
person(charles,24). 

我想創建一個將評估爲真時年齡總和超過40。此外,如果查詢時,它將輸出/顯示其年齡的人的名字的規則加起來是40。所以,我想這:

addsto40(X,Y,Sum) :- person(X,A), person(Y,B), Sum is A + B, Sum > 9. 

當我查詢下它返回兩個人,他們的年齡加起來的數字大於40大的名字(我打,讓所有的解決方案)。查詢的示例:

?- addsto40(X,Y,Sum). 

該查詢返回follwing:

X = brad, 
Y = charles, 
Sum = 44 ; 
X = sophie, 
Y = charles, 
Sum = 42 ; 
X = charles, 
Y = brad, 
Sum = 44 ; 
X = charles, 
Y = sophie, 
Sum = 42 ; 
X = Y, Y = charles, 
Sum = 48. 

但是,這將輸出限制爲對2。我希望它沒有限制,答案可能包括:brad,lindsey和sophie。

我嘗試了一些不成功的解決方案。我考慮過實施addsto40/3,然後添加一個人,直到總和達到40爲止。但是,這並不是我希望它工作的方式。

addsto40(X,Y,Sum) :- person(X,A), person(Y,B), Sum is A + B, Sum < 40, addper(P,Sum,Newsum). 
addsto40(X,Y,Sum) :- person(X,A), person(Y,B), Sum is A + B, Sum > 40. 

addper(Y,Sum,Newsum) :- person(Y,X), Newsum is Sum + X, Newsum < 40, addper(P,Newsum,someSum). 
addper(Y,Sum,Newsum) :- person(Y,X), Newsum is Sum + X, Newsum > 40. 

請問我能被引導到正確的方向嗎?爲什麼這不起作用?該解決方案是否以某種方式實施列表?您對prolog初學者有任何提示或技巧嗎?我很感激任何幫助。謝謝?

+0

請幫幫我! –

回答

1

你應該使用一個列表,因爲你想獲得的人,他們的年齡總和大於40

下面是一個如何可能做到這一點類似於你的方法列表,但使用列表,而不是。

addsto40([H|_],Sum,NewSum) :- person(H,A), NewSum is A + Sum, NewSum > 40. 
addsto40([H|T],Sum,EndSum) :- person(H,A), NewSum is A + Sum, addsto40(T,NewSum,EndSum). 

然後你的查詢是:

addsto40(X,0,Sum). 

但是,你會發現,上面將包括同一人多次和你的列表可以有人們在它的無限數量。爲了解決這個問題,我們添加一個謂詞來檢查列表是否包含特定成員(稱之爲「包含」),並使用它來確保我們不會將同一個人兩次添加到我們的解決方案中。我還會使用助手謂詞來分解開始和(0)和開始列表(空)。最終的代碼如下所示。

addsto40(X,Sum) :- addsto40help(X,0,[],Sum). 

addsto40help([H|_],Sum,Used,NewSum) :- person(H,A), not(contains(H,Used)), NewSum is A + Sum, NewSum > 40. 
addsto40help([H|T],Sum,Used,EndSum) :- person(H,A), not(contains(H,Used)), NewSum is A + Sum, addsto40help(T,NewSum,[H|Used],EndSum). 

contains(X,[X|_]). 
contains(X,[_|T]) :- contains(X,T). 

和您的查詢將是:

addsto40(X,Sum). 
+0

非常感謝,這很有道理。 –