SWI Пролог Использование агрегации
Я создал простую базу данных на SWI Prolog. Моя задача - подсчитать, как долго будет работать каждый из отделов в зависимости от производственного плана. Я почти закончил, но я не знаю, как подвести итоги. На данный момент я получаю что-то вроде этого
сумма отдела
б 20
5
с 50
с 30
как я могу преобразовать это к этому?
б 20
5
с 80
Мой код https://gist.github.com/senioroman4uk/d19fe00848889a84434b
2 ответа
Предоставленный код не будет интерпретировать count
предикат из-за плохого формата. Вы должны переписать это как count:-
вместо count():-
, Насколько я знаю, все нулевые предикаты должны быть определены следующим образом.
Во-вторых, ваш предикат подсчета не собирает результаты в списке, с которым вы могли бы работать. Вот как вы можете изменить его, чтобы собрать все пары отдел-сумма в списке с findall
:
count_sum(DepAmounts):-
findall((Department,Sum),
( productionPlan(FinishedProduct, Amount),
resultOf(FinishedProduct, Operation),
executedIn(Operation, Department, Time),
Sum is Amount * Time
),
DepAmounts
).
Затем, над этим списком, вы можете использовать что-то вроде SWI-Пролога aggregate
:
?- count_sum(L), aggregate(sum(A),L,member((D,A),L),X).
Что даст путем обратного отслеживания отделы в D и сумму сумм в X:
D = a,
X = 15 ;
D = b,
X = 20 ;
D = c,
X = 80.
Кстати, на вашем месте я бы заменил все строки в двойных кавычках для названий отделов и операций и т. Д. Для атомов, для простоты.
Вы должны рассмотреть библиотеку ( агрегат): например, вызывая data/2 интересным подмножеством БД, вы получаете
?- aggregate(set(K-A),aggregate(sum(V),data(K,V),A),L).
L = [a-5, b-20, c-80]