Search code examples
prologaggregateswi-prologprolog-setof

SWI Prolog usage of agregation


I created a simple database on SWI Prolog. My task is to count how long each of departments will work depending on production plan. I am almost finished, but I don't know how to sum my results. As for now I am getting something like this

department amount

b 20

a 5

c 50

c 30

how I can transform it to this?

b 20

a 5

c 80

My code https://gist.github.com/senioroman4uk/d19fe00848889a84434b


Solution

  • The code provided won't interpret the count predicate on account of a bad format. You should rewrite it as count:- instead of count():-. As far as I know, all zero-ary predicates need to be defined like this.

    Second, your count predicate does not collect the results in a list upon which you could operate. Here's how you can change it to collect all department-amount pairs in a list with findall:

    count_sum(DepAmounts):-
        findall((Department,Sum),
                (   productionPlan(FinishedProduct, Amount),
                    resultOf(FinishedProduct, Operation),
                    executedIn(Operation, Department, Time),
                    Sum is Amount * Time
                ),
                DepAmounts
        ).
    

    Then, over that list, you can use something like SWI-Prolog's aggregate:

     ?- count_sum(L), aggregate(sum(A),L,member((D,A),L),X).
    

    Which will yield, by backtracing, departments in D and the sum of the amounts in X:

    D = a,
    X = 15 ;
    D = b,
    X = 20 ;
    D = c,
    X = 80.
    

    BTW, if I were you I'd replace all double-quoted strings for department names and operations and etc. for atoms, for simplicity.