我刚开始学习prolog,我很困惑。
请考虑以下情形:我有一个知识库,其中包含有关人员的事实,格式为人(姓名,年龄)。
示例:
person(brad,20).
person(lindsey,15).
person(sophie,18).
person(charles,24).
我想创建一个规则,当年龄总和超过40时,该规则将评估为true。此外,如果查询,它将输出/显示年龄加起来为40的人的姓名。所以,我试过这个:
addsto40(X,Y,Sum) :- person(X,A), person(Y,B), Sum is A + B, Sum > 9.
当我查询以下内容时,它会返回两个人的名字,这些人的年龄加起来大于40(我点击;获得所有解决方案)。查询示例:
?- addsto40(X,Y,Sum).
此查询返回以下内容:
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.
但是,这会将输出限制为两对。我希望它没有限制因此,答案可能包括例如:布拉德,林赛和索菲。
我尝试了许多不成功的解决方案。我想到实现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).