This is an example of an endless variety of resource allocation tasks for which logic programming is indeed well-suited and frequently used. Related tasks are called transportation and assignment problems in the literature, though the details in this formulation are different. Consider this Prolog formulation as a working starting point with which you can solve such tasks:
distribution([], [], []).
distribution([C-Ps|CPs], Rs0, [C-As|CAs]) :-
allocation(Ps, As, Rs0, Rs1),
As = [_|_],
distribution(CPs, Rs1, CAs).
allocation(_, [], Rs, Rs).
allocation(Ps0, [A|As], Rs0, Rs) :-
select(A, Ps0, Ps1),
select(A, Rs0, Rs1),
allocation(Ps1, As, Rs1, Rs).
distribution/3
expects as its first argument a list of pairs of the form Consumer-Preferences
, and as its second argument a list of resources. It relates this instance description to solutions in the form of pairs Consumer-Allocated resources
. Example query with SWI-Prolog for the concrete task you specified:
?- distribution([a-[x,w],b-[x,y,v],c-[x,z],d-[z]], [x,w,y,v,z], Ds).
Ds = [a-[w], b-[y, v], c-[x], d-[z]] ;
Ds = [a-[w], b-[v, y], c-[x], d-[z]] ;
false.
You can use this formulation for all tasks of this kind. The formulation is complete: It reports all solutions that exist (and some redundantly, because the allocated resources may be stated in any order, as you already see in the example above; you can introduce symmetry breaking constraints in allocation/4
to avoid this - one way to solve this is to insist that As
be ascending with respect to the standard term order), and hence there are no (further) solutions if it answers false
.