Prolog 返回 false 用于求和查询



我是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,而不是给定数据库中已有的值?

忽略我上面的问题!

感谢您的帮助"假"。我还有另一个问题,这次是计算和显示每个成员的收入总和。为了显示它,我修改了我的规则,如下所示:

获取收入(姓名,I) :-

员工(姓名,_,_ ),查找所有(收入,员工(姓名,_,收入),成员),总和(成员,I)。

每当我输入查询时:

?- 获得收入(X,Y)。

我不断得到员工的重复结果(当然,最值得注意的是安迪),如下所示:

X = 安迪,
Y = 8 ;
X = 贝丝,
Y = 4 ;
X = 安迪,
Y = 8 ;
X = 卡尔,
Y = 2 ;
X = 伯爵,
Y = 9。

我可以进行哪些更改来避免这些重复?

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.

一种方法是使用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谓词。

最新更新