汇总多个事实的解决方案

时间:2016-03-10 07:12:16

标签: prolog duplicates aggregate

尝试创建一个谓词(timePeriod/2),用于计算特定事实的两个日期之间的时间段。我自己设法做到了这一点,但是当“其他答案”存在于同一列表中时面临问题(即更容易用示例解释)。

我有以下知识基础事实;

 popStar('Jackson',1987,1991).
 popStar('Jackson',1992,1996).
 popStar('Michaels',1996,2000).
 popStar('Newcastle',2000,2007).
 popStar('Bowie',2008,2010).

以下函数计算特定事实的日期之间的时间(如下所示)。

谓词(timePeriod / 2) -

 timePeriod(PS,X) :-
    bagof((Name,Start,End),popStar(Name,Start,End),PSs),X is End-Start+1)

以鲍伊为例;它返回X=3(这是正确的)。

但是,当列表中有重复时,如果有多个答案可用,则谓词只会声明“false”。以事实'杰克逊'为例,我希望能够计算两个事实的两个时间段;同时。

因此,如果谓词适用于两个杰克逊事实,则谓词timePeriod将表示X=10

如果有人可以建议改变什么来使其正常工作,我们将非常感激。

感谢。

2 个答案:

答案 0 :(得分:2)

您可能不太了解foreach/3的作用。我不认为我完全理解foreach/3。我肯定知道和说:

相同
for each x in xs:
    do foo(x)

另一件事:Prolog中的“元组”并不是你所期望的,来自像Python或Haskell这样的语言。这个:(a,b,c)实际上就是这样:','(a,','(b,c))。更好的是使用平面术语,通用形式将是triple(a,b,c)。对于一对,成语是First-Second

因此,您可以简化对此bagof/3的调用:

?- bagof(From-To, pop_star(Name, Start, End), Ts).
Name = 'Bowie',
Ts = [2008-2010] ;
Name = 'Jackson',
Ts = [1987-1991, 1992-1996] ;
Name = 'Michaels',
Ts = [1996-2000] ;
Name = 'Newcastle',
Ts = [2000-2007].

如果你有一个上面的列表,你需要总结差异,这可能是这样的:

periods_total(Ps, T) :-
    maplist(period_length, Ps, Ls),
    sum_list(Ls, T).

period_length(From-To, Length) :-
    Length is To - From + 1.

然后你可以像这样查询:

?- bagof(From-To, pop_star('Jackson', From, To), Ps), periods_total(Ps, T).
Ps = [1987-1991, 1992-1996],
T = 10.

?- bagof(From-To, pop_star(Name, From, To), Ps), periods_total(Ps, T).
Name = 'Bowie',
Ps = [2008-2010],
T = 3 ;
Name = 'Jackson',
Ps = [1987-1991, 1992-1996],
T = 10 ;
Name = 'Michaels',
Ps = [1996-2000],
T = 5 ;
Name = 'Newcastle',
Ps = [2000-2007],
T = 8.

答案 1 :(得分:0)

SWI-Prolog有一个很好的library来处理聚合:它基于标准的所有解决方案'像findall / 3,setof / 3,bagof / 3这样的谓词,所以你应该首先掌握这些的基本原理(正如鲍里斯在他的回答中所解释的那样)。使用该库,单个查询可以解决您的问题:

<table><tr>
<th>
<p align="center">22/02/16<br />to<br />27/02/16</p>
</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font color="red" size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font color="red" size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<p>          </font></tr>
<tr>
<th>
<p align="center">29/02/16<br />to<br />05/03/16</p>
</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font color="red" size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font color="red" size="6">xx</font></th>
<th>x<br />x<br />x</th>
<p> </font></tr>
<tr>
<th>
<p align="center">07/03/16<br />to<br />12/03/16</p>
</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<p>          </font></tr>
<tr>
<th>
<p align="center">14/03/16<br />to<br />14/03/16</p>
</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<th>x<br />x<br />x</th>
<th><font size="6">xx</font></th>
<th>x<br />x<br />x</th>
<p>          </font></tr></table>