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]
Другие вопросы по тегам