2017-04-23 56 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

非常感谢,这很有道理。 –