weekend xii

This commit is contained in:
Yorick van Pelt 2019-02-18 11:36:35 +01:00
parent 842c773be0
commit 6b72a56fc6
No known key found for this signature in database
GPG Key ID: D8D3CC6D951384DE
4 changed files with 137 additions and 130 deletions

View File

@ -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]

View File

@ -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)

View File

@ -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;

View File

@ -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