weekend xii
This commit is contained in:
parent
842c773be0
commit
6b72a56fc6
144
config.yaml
144
config.yaml
@ -1,112 +1,106 @@
|
||||
config:
|
||||
days: 3
|
||||
days: 4
|
||||
weights:
|
||||
likes: 1
|
||||
hates: 3
|
||||
# TODO: load_dev
|
||||
ignore: ["(vega)"]
|
||||
ignore: []
|
||||
task_re: "[ ,/]+"
|
||||
tasks:
|
||||
hotemetoten:
|
||||
personen: [Linda, Yorick, avel]
|
||||
personen: [Lucus, Yorick, Sjors, MacGyver, Linda, Wassasin]
|
||||
workload: 4
|
||||
req: [1, 1, 1]
|
||||
req: [1, 1, 1, 1]
|
||||
hardcode:
|
||||
- Linda # dag 1
|
||||
halen:
|
||||
req: [3, 0, 0]
|
||||
personen: [Colin, Petervdv, MacGyver]
|
||||
workload: 4
|
||||
baktaarten:
|
||||
req: [0, 6, 0]
|
||||
personen: [Linda, joshua, obfusk (felix), alphacentauri, tessa, nanette]
|
||||
workload: 2
|
||||
taartpiet:
|
||||
req: [0, 4, 0]
|
||||
personen: iedereen
|
||||
workload: 2
|
||||
- Wassasin
|
||||
- lucus
|
||||
- Yorick
|
||||
- Sjors
|
||||
lookup: [hotemetoten]
|
||||
superkok:
|
||||
req: [1, 1, 1]
|
||||
personen: [macgyver, bas, lucus]
|
||||
req: [1, 1, 1, 1]
|
||||
personen: [linda, pepper, bwesterb, tommeh]
|
||||
workload: 4
|
||||
hardcode:
|
||||
- macgyver # dag 1
|
||||
- bas # dag 2
|
||||
- lucus # dag 3
|
||||
lookup: [superkok]
|
||||
hardcode:
|
||||
- Linda
|
||||
- Pepper
|
||||
- bwesterb
|
||||
- tommeh
|
||||
drankmanagen:
|
||||
req: [1, 1, 1, 1]
|
||||
personen: [MacGyver]
|
||||
workload: 1
|
||||
lookup: [drankmanagen]
|
||||
koken:
|
||||
req: [3, 3, 3]
|
||||
req: [4, 2, 2, 2]
|
||||
workload: 3
|
||||
personen: liefhebbers
|
||||
lookup: [koken, kookhulp]
|
||||
lookup: [koken, kookhulp, hulpkoken]
|
||||
schoonmaken:
|
||||
req: [4, 4, 4]
|
||||
req: [3, 4, 4, 4]
|
||||
workload: 2
|
||||
personen: iedereen
|
||||
lookup: [schoonmaken]
|
||||
snackdealen:
|
||||
req: [6, 6, 6]
|
||||
req: [4, 5, 5, 5]
|
||||
workload: 1
|
||||
personen: iedereen
|
||||
lookup: [hapjes]
|
||||
lookup: [hapjes, snackdealen]
|
||||
fotograferen:
|
||||
req: [2, 2, 2]
|
||||
req: [2, 2, 2, 2]
|
||||
workload: 1
|
||||
personen: liefhebbers
|
||||
lookup: [fotograferen, fototroep]
|
||||
lookup: [fotograferen]
|
||||
afwassen:
|
||||
req: [5, 5, 5]
|
||||
req: [4, 4, 4, 4]
|
||||
workload: 2
|
||||
personen: iedereen
|
||||
lookup: [afwassen]
|
||||
snijpieten:
|
||||
req: [0, 5, 5]
|
||||
req: [5, 4, 4, 4]
|
||||
workload: 2
|
||||
personen: iedereen
|
||||
|
||||
lookup: [snijden]
|
||||
people:
|
||||
- Loeka
|
||||
- Petervdv
|
||||
- Margot
|
||||
- Yorick
|
||||
- linda
|
||||
- Colin
|
||||
- Sjors
|
||||
- Erik
|
||||
- weasel
|
||||
- Minnozz
|
||||
- Lucus
|
||||
- avel
|
||||
- Daan
|
||||
- Felix
|
||||
- Maurice
|
||||
- Marlon
|
||||
- Hannah
|
||||
- bas
|
||||
- Ed
|
||||
- Ilona
|
||||
- AlphaCentauri
|
||||
- Joost
|
||||
- Blondie
|
||||
- Nanette
|
||||
- MacGyver:
|
||||
max_load: [2, 0, 0]
|
||||
- Pepper
|
||||
- MrNGm
|
||||
- quis
|
||||
- Nick
|
||||
- roflincopter
|
||||
- obfusk (Felix)
|
||||
- SyntaxTerror
|
||||
- Tom de Ruijter
|
||||
- annelies
|
||||
- roy
|
||||
- PaxSum
|
||||
- Yorick
|
||||
- Sjors
|
||||
- MacGyver
|
||||
- Linda
|
||||
- Wassasin
|
||||
- Abel
|
||||
- Daan
|
||||
- MrNGm
|
||||
- Petervdv
|
||||
- Minnozz
|
||||
- Nova
|
||||
- Joost
|
||||
- Obfusk:
|
||||
dagen: []
|
||||
- Marlon
|
||||
- Pepper
|
||||
- PaxSum: # vrijdag
|
||||
dagen: [1,2,3]
|
||||
- M-ou-se
|
||||
- Annelies
|
||||
- Weasel
|
||||
- Carrot
|
||||
- Roflincopter
|
||||
- Bwesterb
|
||||
- Tommeh: # vrijdag
|
||||
dagen: [1,2,3]
|
||||
- NickNick
|
||||
- Quis
|
||||
- SyntaxTerror
|
||||
- ElizaAntoine
|
||||
- carrot
|
||||
- eric s
|
||||
- Mike Koeman
|
||||
- Joshua
|
||||
- Tessa
|
||||
- Abel
|
||||
- Carlien
|
||||
- Blondie
|
||||
- Avel: # vrijdag
|
||||
dagen: [1,2,3]
|
||||
- Thundur: # vrijdag
|
||||
dagen: [1,2,3]
|
||||
- Ayke
|
||||
- Hannah
|
||||
- Cocidius:
|
||||
dagen: [1,2,3]
|
||||
|
@ -6,14 +6,23 @@ import re
|
||||
import subprocess
|
||||
from collections import OrderedDict
|
||||
import glpm
|
||||
conf = yaml.load(open('config.yaml', 'r'))
|
||||
config = conf['config']
|
||||
config['ignore'].append('')
|
||||
tasks = OrderedDict(conf['tasks'])
|
||||
index = lambda x: {v:k for k,v in enumerate(x)}
|
||||
daily_workloads = \
|
||||
[sum(task['workload'] * task['req'][d] for task in tasks.values()) for d in range(config['days'])]
|
||||
ALL_DAYS = set(range(config['days']))
|
||||
class Person(object):
|
||||
def __init__(self, conf={}):
|
||||
def __init__(self, conf={"dagen":ALL_DAYS}):
|
||||
self.can = set()
|
||||
self.loves = set()
|
||||
self.hates = set()
|
||||
self.does = set() # hardcoded
|
||||
self.has_prefs = False
|
||||
self.conf = conf
|
||||
self.conf['dagen'] = set(conf['dagen'])
|
||||
def vrolijkheid(self):
|
||||
res = config['days'] - len(self.does)
|
||||
for (d,t) in self.does:
|
||||
@ -24,17 +33,15 @@ class Person(object):
|
||||
return res
|
||||
def workload(self, tasks):
|
||||
return sum(tasks[t]['workload'] for (d,t) in self.does)
|
||||
conf = yaml.load(open('config.yaml', 'r'))
|
||||
config = conf['config']
|
||||
config['ignore'].append('')
|
||||
tasks = OrderedDict(conf['tasks'])
|
||||
index = lambda x: {v:k for k,v in enumerate(x)}
|
||||
def cost(self, num_people):
|
||||
return round(sum((daily_workloads[d] for d in self.conf['dagen'])) / num_people)
|
||||
# probabilistic round: int(math.floor(x + random.random()))
|
||||
def read_people(conf_ppl):
|
||||
def isdict(x):
|
||||
return type(x) == dict
|
||||
people = OrderedDict()
|
||||
for x in conf_ppl:
|
||||
val = {}
|
||||
val = {"dagen": ALL_DAYS}
|
||||
if type(x) == dict:
|
||||
x,val = x.popitem()
|
||||
people[x.lower()] = Person(val)
|
||||
@ -86,6 +93,7 @@ def matrices(people, tasks):
|
||||
tsk_idx = index(tasks)
|
||||
hardcode = {}
|
||||
max_loads = {}
|
||||
costs = {}
|
||||
for i,(person, p) in enumerate(people.items()):
|
||||
for t in p.loves: loves[i][tsk_idx[t]] = 1
|
||||
for t in p.hates: hates[i][tsk_idx[t]] = 1
|
||||
@ -94,12 +102,16 @@ def matrices(people, tasks):
|
||||
if 'max_load' in p.conf: # max_load override for Pol
|
||||
for d,l in enumerate(p.conf['max_load']):
|
||||
max_loads[(i,d)] = l
|
||||
# filter days that the person does not exist
|
||||
for d in ALL_DAYS - p.conf['dagen']:
|
||||
max_loads[(i,d)] = 0
|
||||
costs[i] = p.cost(len(people))
|
||||
req = mat(range(config['days']), tasks)
|
||||
for di in range(config['days']):
|
||||
for ti,t in enumerate(tasks.values()):
|
||||
req[di][ti] = t['req'][di]
|
||||
workload = {tsk_idx[t]: tasks[t]['workload'] for t in tasks}
|
||||
return [loves, hates, capab, hardcode, max_loads, req, workload]
|
||||
return [loves, hates, capab, hardcode, max_loads, req, workload, costs]
|
||||
def read_assignment(file, people, tasks):
|
||||
def between_the_lines(f, a=">>>>\n", b="<<<<\n"):
|
||||
for l in f:
|
||||
@ -115,7 +127,7 @@ def read_assignment(file, people, tasks):
|
||||
for [p,d,j,W,l] in between_the_lines(file):
|
||||
person_vl[p-1].does.add((d-1, task_nm[j-1]))
|
||||
def write_data(people, tasks, file=sys.stdout):
|
||||
[loves, hates, capab, hardcode, max_loads, req, workload] = matrices(people, tasks)
|
||||
[loves, hates, capab, hardcode, max_loads, req, workload, costs] = matrices(people, tasks)
|
||||
print(glpm.matrix("L", loves), file=file)
|
||||
print(glpm.matrix("H", hates), file=file)
|
||||
print(glpm.matrix("C", capab, 1), file=file)
|
||||
@ -123,6 +135,7 @@ def write_data(people, tasks, file=sys.stdout):
|
||||
print(glpm.dict("Q", hardcode), file=file)
|
||||
print(glpm.dict("Wl", workload), file=file)
|
||||
print(glpm.dict("max_load", max_loads), file=file)
|
||||
print(glpm.dict("Costs", costs), file=file)
|
||||
print(glpm.param("D_count", config['days']), file=file)
|
||||
print(glpm.param("P_count", len(people)), file=file)
|
||||
print(glpm.param("J_count", len(tasks)), file=file)
|
||||
@ -130,12 +143,12 @@ def write_data(people, tasks, file=sys.stdout):
|
||||
print(glpm.param("WH", config['weights']['hates']), file=file)
|
||||
def write_tasks(people, tasks, file=sys.stdout):
|
||||
for name, p in people.items():
|
||||
days = [[],[],[]]
|
||||
days = [[] for i in range(config['days'])]
|
||||
for (d,t) in p.does:
|
||||
days[d].append((t, t in p.loves))
|
||||
q = lambda w: ",".join([x[0] + " <3" if x[1] else x[0] for x in w])
|
||||
print("| {} || {} || {} || {} || {} || {}".format(name, *map(q, days), p.vrolijkheid(), p.workload(tasks)), file=file)
|
||||
# print("|-")
|
||||
days[d].append((t, t in p.loves, t in p.hates))
|
||||
q = lambda w: ",".join([t + (" <3" if l else "") + (" :(" if h else "") for (t,l,h) in w])
|
||||
print("| {} || {} || {} || {} || {} || {} || {}".format(name, *map(q, days), p.vrolijkheid(), p.workload(tasks)), file=file)
|
||||
print("|-")
|
||||
people = read_people(conf['people'])
|
||||
with open('prefs_table', 'r') as pref_file:
|
||||
read_prefs(pref_file, tasks, people)
|
||||
@ -149,7 +162,7 @@ elif len(sys.argv)>1 and sys.argv[1] == 'out':
|
||||
else:
|
||||
with open('data', 'w') as out:
|
||||
write_data(people, tasks, file=out)
|
||||
subprocess.call(["glpsol", "--model", "model.glpm", "-d", "data", "--tmlim", "30", "--log", "output"], stdout=sys.stderr, stderr=sys.stdout)
|
||||
subprocess.call(["glpsol", "--model", "model.glpm", "-d", "data", "--tmlim", "15", "--log", "output"], stdout=sys.stderr, stderr=sys.stdout)
|
||||
with open('output', 'r') as file:
|
||||
read_assignment(file, people, tasks)
|
||||
write_tasks(people, tasks)
|
||||
|
14
model.glpm
14
model.glpm
@ -14,6 +14,10 @@ set P := 1..P_count;
|
||||
set J := 1..J_count;
|
||||
set D := 1..D_count;
|
||||
|
||||
/* aanwezigheid x workload for that day */
|
||||
param Costs{p in P}, integer, >= 0;
|
||||
|
||||
|
||||
/* Person p likes to solve jobs j */
|
||||
param L{p in P, j in J} default 0, binary;
|
||||
|
||||
@ -48,7 +52,7 @@ s.t. max_load_person{p in P, d in D}: sum{j in J} A[p,j,d] <= max_load[p,d];
|
||||
#s.t. min_load_person{p in P}: sum{j in J, d in D} A[p,j,d] >= min_load[p];
|
||||
|
||||
/* A person does not perform the same job on all days */
|
||||
s.t. duplicate_jobs{p in P, j in J}: sum{d in D} A[p,j,d] <= D_count-1;
|
||||
/*s.t. duplicate_jobs{p in P, j in J}: sum{d in D} A[p,j,d] <= D_count-1;*/
|
||||
|
||||
/* Each task is allocated */
|
||||
s.t. all_allocated{j in J, d in D}: sum{p in P} A[p,j,d] == R[d, j];
|
||||
@ -56,8 +60,8 @@ s.t. all_allocated{j in J, d in D}: sum{p in P} A[p,j,d] == R[d, j];
|
||||
/* A person only performs what (s)he is capable of */
|
||||
s.t. capability_person{p in P, j in J, d in D}: A[p,j,d] <= C[p,j];
|
||||
|
||||
s.t. error_lt{p in P}: error[p] >= ((sum{j in J, d in D} A[p,j,d] * Wl[j]) - 4);
|
||||
s.t. error_gt{p in P}: error[p] >= 4 - (sum{j in J, d in D} A[p,j,d] * Wl[j]);
|
||||
s.t. error_lt{p in P}: error[p] >= ((sum{j in J, d in D} A[p,j,d] * Wl[j]) - Costs[p]);
|
||||
s.t. error_gt{p in P}: error[p] >= Costs[p] - (sum{j in J, d in D} A[p,j,d] * Wl[j]);
|
||||
|
||||
/* Maximize enjoyment */
|
||||
# minimize error_diff: sum{p in P} error[p];
|
||||
@ -71,8 +75,8 @@ printf{p in P, d in D, j in J : A[p,j,d] > 0} "%d %d %d %d %d\n", p, d, j, A[p,j
|
||||
printf "<<<<\n";
|
||||
printf "workloads\n";
|
||||
printf "p l\n";
|
||||
printf{p in P} "%d %d\n", p, abs((sum{j in J, d in D : A[p,j,d] > 0} Wl[j]) - ((sum{d in D, j in J} Wl[j] * R[d,j]) / P_count));
|
||||
printf "workload_dev: %d\n", sum{p in P} abs((sum{j in J, d in D : A[p,j,d] > 0} Wl[j]) - ((sum{d in D, j in J} Wl[j] * R[d,j]) / P_count))^2;
|
||||
printf{p in P} "%d %d\n", p, abs((sum{j in J, d in D : A[p,j,d] > 0} Wl[j]) - Costs[p]);
|
||||
printf "workload_dev: %d\n", sum{p in P} abs((sum{j in J, d in D : A[p,j,d] > 0} Wl[j]) - Costs[p])^2;
|
||||
|
||||
|
||||
end;
|
66
prefs_table
66
prefs_table
@ -1,35 +1,31 @@
|
||||
Weasel schoonmaken/afwassen/kookhulp hapjes
|
||||
Petervdv schoonmaken, afwassen, hapjes koken, fotograferen
|
||||
Daan fotograferen, kookhulp hapjes, schoonmaken
|
||||
Bas superkok afwassen, schoonmaken
|
||||
Lucus superkok, hapjes fotograferen, schoonmaken
|
||||
mrngm kookhulp, afwassen hapjes
|
||||
Nick hapjes, schoonmaken afwassen
|
||||
obfusk (Felix) koken (vega) fotograferen
|
||||
PaxSum kookhulp, afwassen fotograferen, schoonmaken
|
||||
ElizaAntoine afwassen, schoonmaken hapjes, koken
|
||||
SyntaxTerror fotograferen, afwassen, schoonmaken hapjes, koken
|
||||
Abel fotograferen, afwassen, schoonmaken hapjes, koken
|
||||
Annelies fotograferen, afwassen hapjes
|
||||
Roflincopter schoonmaken, kookhulp fotograferen
|
||||
carrot kookhulp, afwassen fotograferen
|
||||
MacGyver superkok schoonmaken
|
||||
Felix afwassen, kookhulp fotograferen, hapjes
|
||||
Eric S kookhulp, afwassen, schoonmaken hapjes, fotograferen
|
||||
Sjors afwassen, hapjes schoonmaken
|
||||
AlphaCentauri fotograferen, hapjes schoonmaken, koken
|
||||
Blondie koken, hapjes schoonmaken
|
||||
Nanette fotograferen hapjes
|
||||
Loeka kookhulp, hapjes afwassen
|
||||
Marlon koken afwassen
|
||||
Joost kookhulp, afwassen, schoonmaken hapjes, fotograferen
|
||||
Erik koken, fotograferen schoonmaken, hapjes
|
||||
Roy koken, hapjes, fotograferen afwassen, schoonmaken
|
||||
Joshua koken
|
||||
Tessa hapjes
|
||||
Ed fotograferen, afwassen, schoonmaken hapjes, koken
|
||||
Margot afwassen, schoonmaken
|
||||
Colin afwassen, koken schoonmaken
|
||||
Pepper kookhulp, afwassen, schoonmaken hapjes
|
||||
Ilona afwassen
|
||||
Quis koken, hapjes schoonmaken, fototroep
|
||||
Lucus koken schoonmaken, fotograferen
|
||||
Wassasin koken fotograferen
|
||||
linda superkok, snackdealen koken, snijden, afwassen, schoonmaken, fotograferen
|
||||
Nova koken, afwassen fotograferen, snackdealen
|
||||
Obfusk koken, afwassen fotograferen, snackdealen, schoonmaken
|
||||
Daan fotograferen, koken schoonmaken
|
||||
Pepper superkok
|
||||
Roflincopter snijden, afwassen, schoonmaken snackdealen, fotograferen, koken
|
||||
SyntaxTerror fotograferen, snijden, afwassen koken
|
||||
Annelies fotograferen, afwassen, koken snackdealen
|
||||
Joost snijden, koken, afwassen fotograferen, snackdealen
|
||||
MrNGm koken, snijden, schoonmaken, fotograferen
|
||||
PaxSum koken, snijden, afwassen Fotograferen, snackdealen
|
||||
Weasel hulpkoken, snijden, fotograferen snackdealen, schoonmaken
|
||||
NickNick snackdealen, snijden, koken schoonmaken, afwassen
|
||||
carrot snijden, koken, afwassen schoonmaken, snackdealen
|
||||
bwesterb superkok, snijden schoonmaken, snackdealen, afwassen
|
||||
Minnozz koken schoonmaken
|
||||
ElizaAntoine snijden, schoonmaken, afwassen snackdealen, koken
|
||||
Ayke koken, snijden, afwassen
|
||||
Cocidius koken, snijden, afwassen schoonmaken
|
||||
Blondie fotograferen, koken schoonmaken, snackdealen
|
||||
Thundur snijden, koken, afwassen snackdealen, fotograferen
|
||||
Tommeh superkok
|
||||
Petervdv snackdealen fotograferen, koken, afwassen
|
||||
Abel fotograferen, afwassen
|
||||
Avel fotograferen, schoonmaken, snackdealen snijden, afwassen
|
||||
Sjors snackdealen, schoonmaken koken
|
||||
Carlien snackdealen, schoonmaken koken
|
||||
Quis snackdealen, snijden, koken schoonmaken, fotograferen
|
||||
MacGyver drankmanagen
|
Loading…
Reference in New Issue
Block a user