在Prolog的列表中合并元组的元素



我需要从知识库创建一个列表,如下所示:

fact1(3,3).
fact1(2,3).
fact1(3,5).
fact1(2,2).
fact1(2,10).
fact1(3,1).
fact1(1,1).
fact1(1,6).
fact2(3,a,b)
fact2(2,c,d)
fact2(1,e,f)

该列表需要包含元组,每个元组包含 fact2 的第二个和第三个值,以及 fact2 的添加数,只要 fact1 和 fact2 的第一个值匹配。

也许当我展示到目前为止我所拥有的东西时,它会变得更清楚。 这是我对findall语句的谓词,对我来说,这似乎让我最接近我需要得到的地方:

collect_items(List):-
findall((Out1,Out2,Nr),
(fact2(Val1,Out1,Out2),
fact1(Val1,Nr)),
List).

我从中收到的列表如下所示:

List = [(a,b,3),(a,b,5),(a,b,1),(c,d,3),(c,d,2),(c,d,10),(e,f,1),(e,f,6)]

但实际上我需要列表看起来像这样:

List = [(a,b,9),(c,d,15),(e,f,7)]

这意味着,每当元组的前两个元素匹配时,作为元组第三个元素的数字应该相加。

然而,我不知道如何处理这样的事情,正如我一直读到的那样,一旦设置了列表,就无法更改,因为 prolog 是功能性和声明性的。

所以我认为我需要以某种方式将每个元素与它之前或之后的元素进行匹配(因为列表将始终按 Out1 和 Out2 变量排序),如果它们匹配,则将元组中的第三个值加在一起。问题是,我不知道怎么做。

对我来说,看起来这不能在 findall 本身内完成,而是需要在 findall 之后完成 我是一个真正的初学者,将不胜感激任何帮助。在这种情况下,如果解决方案全部在一个谓词中,那将是最好的。

下面是使用多个谓词的另一种解决方案:

collect_items(Result):-
findall([Out1,Out2,Nr],(fact2(Val1,Out1,Out2),fact1(Val1,Nr)),[[OutA, OutB, N]|B]), 
sumElements([[OutA, OutB, N]|B], Result).
sumElements([],[]).
sumElements([[Out, Outt, N]|B], [[Out, Outt, SumLocal]|RestOfList]):-
findall([Out, Outt, X], member([Out, Outt, X], [[Out, Outt, N]|B]), SubList),
sumLocal(SubList, SumLocal),
subtract([[Out, Outt, N]|B], SubList, New),
sumElements(New, RestOfList).
sumLocal([],0).
sumLocal([[_,_,S]|B], T):-
sumLocal(B, R),
T is S + R.

输出:

?- collect_items(Result).
Result = [[a, b, 9], [c, d, 15], [e, f, 7]].

带有库聚合:

collect_items(L) :-
setof((U,V,S),
K^aggregate((set(X/Y),sum(N)), (
fact2(K,X,Y),
fact1(K,N)
), ([U/V],S)), L).

我们得到

?- collect_items(L).
L = [(a, b, 9),  (c, d, 15),  (e, f, 7)].

你不在这里

因为Prolog是功能性和声明性的

Prolog是关系性的和声明性的

最新更新