-
Notifications
You must be signed in to change notification settings - Fork 0
/
allocation.py
65 lines (57 loc) · 1.59 KB
/
allocation.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# use pulp to calculate the allocation via an LP
from pulp import *
#def expr(s, vars):
# return fd.make_expression( vars, s % vars )
def var(p, t):
"""Return the variable associated with this person and task."""
v = "x_" + str(p) + "_" + str(t)
if not v in var.vars:
var.vars[v] = LpVariable(v, cat = "Binary")
var.info[v] = (p, t)
return var.vars[v]
var.vars = {}
var.info = {}
def rate(s):
if s == 'y': return 1
if s == 'm': return 0.5
return 0
def allocate(persons, tasks):
"""Calculate an allocation of tasks to persons."""
prob = LpProblem()
# list of person and task ids
pids = range(len(persons))
tids = range(len(tasks))
# objective
obj = LpAffineExpression()
# Make sure each person gets exactly one task.
for p in pids:
constraint = 0
for t in tids:
# no => bind variable to zero
if persons[p][1][t] == "n":
prob += var(p,t) == 0
# yes => add to constraint and objective
if persons[p][1][t] == "y":
constraint += var(p,t)
obj += var(p,t)
# maybe => add to constraint and objective (with lower priority)
if persons[p][1][t] == "m":
constraint += var(p,t)
obj += 2*var(p,t)
prob += constraint == 1
# Make sure each task is done at most once.
for t in tids:
constraint = 0
for p in pids:
if persons[p][1][t] in ["y","m"]:
constraint += var(p,t)
prob += constraint <= 1
# Add objective.
prob += obj
status = prob.solve(GLPK(msg = False))
enabled = []
for v in var.vars:
if value(var.vars[v]) == 1:
(p,t) = var.info[v]
enabled.append( (persons[p][0], tasks[t]) )
return (status, enabled, lambda p,t: (p,t) in enabled)