我是Prolog的新手,因为我刚开始学习并编写自己的一小组数据库规则。使用我自己的数据库规则的.pl文件,我在使用这些规则在Prolog中输入的查询遇到了一个小问题。下面显示了我的小规则数据库:
staff(andy,18235,3).
staff(beth,19874,4).
staff(andy,18235,5).
staff(carl,16789,2).
staff(earl,34567,9).
sum([], 0).
sum([H|T], X) :-
sum(T, X1),
X is X1 + H.
getincome(Name, Income) :-
findall(Income,staff(Name,_,Income),Member),
sum(Member, Income).
正如您所看到的,我编写了一条规则,查明特定员工的总收入。这很好用,就像我输入的那样:
?- getincome(andy, X).
程序总是返回:
X = 8
正如它应该做的那样,无论何时我改为输入:
?- getincome(andy, 8).
当它应该为真时,它总是返回false。
然而,当我也输入:
?- getincome(andy, 3).
由于已经存在于数据库中,因此返回true。
我只是想知道,我怎么能修改这个规则,这样就可以为任何给定的员工(最特别是Andy)输入的正确求和值输出true,而不是给定数据库中的值? / p>
忽略我上面的问题!
感谢'错误'的帮助。我还有另一个问题,这次是为了解决并显示每个成员的收入总和。我修改了我的规则,以便显示如下:
getincome(姓名,I): - 员工(姓名,_,_),findall(收入,员工(姓名,_,收入),会员),总和(会员,I)。
每当我输入查询时:
? - getincome(X,Y)。
我不断得到工作人员的重复结果(当然最着名的是Andy),如下所示:
X = andy,
Y = 8;
X = beth,
Y = 4;
X = andy,
Y = 8;
X = carl,
Y = 2;
X =伯爵,
Y = 9.
我可以做些什么改变来避免这些重复?
答案 0 :(得分:1)
library(aggregate)提供了一个干净的界面来解决这类问题:
?- aggregate(sum(S), K^staff(E,K,S), I).
E = andy,
I = 8 ;
E = beth,
I = 4 ;
E = carl,
I = 2 ;
E = earl,
I = 9.
答案 1 :(得分:0)
这样做的一种方法是使用bagof
来收集每组收入:
person_income(Name, Income) :-
bagof(I, X^staff(Name,X,I), Incomes), % Incomes for a given name
sumlist(Incomes, Income). % Sum the incomes
结果:
| ?- person_income(Name, Income).
Income = 8
Name = andy ? a
Income = 4
Name = beth
Income = 2
Name = carl
Income = 9
Name = earl
yes
| ?- person_income(andy, Income).
Income = 8
yes
| ?- person_income(Name, 8).
Name = andy ? a
no
| ?-
我将此命名为person_income
,以强调这是一个人与他们的收入之间的关系,而不是getincome
这更像是一种命令性的概念,并不能真正反映出你可以做得更多与关系不仅仅是“获得收入”。另外,我在这里使用SWI Prolog的sumlist/2
。 GNU Prolog有sum_list/2
。正如@CappeliC在他的回答中指出的那样,SWI Prolog对于这样的操作有一个方便的aggregate
谓词。