I run into this beginners problem, and i don't know how to solve this. Here is my code:
worker( w1, d1, 2000 ) .
worker( w2, d1, 2500 ) .
worker( w2, d2, 1000 ) .
worker( w3, d2, 2000 ) .
worker( w4, d2, 4000 ) .
% worker( W, D, S ) means that worker W works in department D and has salary S
department( d1, w2 ) .
department( d2, w4 ) .
% department( D, B ) means that worker B is director of department D(this is not important in this case)
I need to get sum of all salaries form one of department, like this:
?- department_costs( d1 , T ) .
T = 4500;
no
?- department_costs( D, T ) .
D = d1
T = 4500;
D = d2
T = 7000;
no
?- department_costs( d3 , T ) .
no
I tried this:
department_costs( D, T ):- worker( _X, D, T1 ), T is T1.
And I get this:
?- department_costs( o1, T ).
T=2000;
T=2500;
no
now I need to sum T+T for total costs, but I don't know how to do that. I would like to solve this without using findall/setof/bagof.
EDIT:
I tried with findall:
sumL([], 0).
sumL([G|R], S):-
sumL(R, S1),
S is S1 + G.
department_costs( D, T ):-
findall(P, worker( _X, D, P ), R ),
sumL(R, S),
T=S.
It works fine with department_costs( d1, T ), and department_costs( d2, T ), but when I enter department_costs( D, T ). i get this:
department_costs( D, T ).
O=_h159
T=11500
and it should be like this:
?- department_costs( D, T ) .
D = d1
T = 4500;
D = d2
T = 7000;
can someone tell what is the problem now?
Wanting to solve this without findall/3 will just result in a poor attempt at recoding said findall/3. If you really wanna skip findall/3, represent your data in a different way, for example:
workers([w1-d1-2000, w2-d1-2500, w2-d2-1000, w3-d2-2000, w4-d2-4000]).
departments([d1-w2, d2-w4]).
In this format you will be able to use recursion and list processing techniques to achieve a good result. In the previous one you will have to go with either database manipulation and/or global variables. Not really Prolog-ish.
For your edit, the problem is that you use findall/3, and that findall/3 will give you all the results for the one variable you're interested in, but will not precise the bindings that led to those results.
Try bagof/3 instead:
bagof(S, W^worker( W, D, S ), R ).
And see this man page (even if it's SWI, those are ISO Prolog predicates anyway) for more information.
library(aggregate) is meant to solve exactly such kind of problems. It's worth to study.
department_costs( D, T ) :- aggregate_all(sum(C), worker( _, D, C ), T).
edit
XSB has 'Tabling Aggregate Predicates' that should allow you to solve efficiently your problem.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With