Prolog为求和查询返回false

时间:2015-01-11 16:33:45

标签: prolog

我是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.

我可以做些什么改变来避免这些重复?

2 个答案:

答案 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谓词。