fix everything

This commit is contained in:
Yorick van Pelt 2018-02-14 16:43:28 +01:00
parent f58ba0f37d
commit 842c773be0
7 changed files with 402 additions and 322 deletions

View File

@ -1,210 +0,0 @@
/* Number of people */
param P_count, integer, > 0;
/* Number of jobs */
param J_count, integer, > 0;
/* Number of days */
param D_count, integer, > 0;
param WL, integer, > 0;
param WH, integer, > 0;
set P := 1..P_count;
set J := 1..J_count;
set D := 1..D_count;
/* Person p likes to solve jobs j */
param L{p in P, j in J} default 0, binary;
/* Person p hates to solve jobs j */
param H{p in P, j in J} default 0, binary;
/* Person p is capable to perform job j */
param C{p in P, j in J} default 1, binary;
/* How many jobs need to be done on what day */
param R{d in D, j in J}, integer, >= 0;
/* hardcoded */
param Q{p in P, j in J, d in D}, default 0, binary;
/* workload */
param Wl{j in J}, integer, >= 0;
param max_load{p in P, d in D}, default 1, integer;
/* Person p is allocated to do job j on day d */
var A{p in P, j in J, d in D}, binary;
var error{p in P}, integer, >= 0;
s.t. hardcode{p in P, j in J, d in D}: A[p,j,d] >= Q[p,j,d];
/* A person only has one task per day, at most */
s.t. max_load_person{p in P, d in D}: sum{j in J} A[p,j,d] <= max_load[p,d];
/* A person has at least D-1 tasks */
#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;
/* 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];
/* 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]);
/* Maximize enjoyment */
# minimize error_diff: sum{p in P} error[p];
maximize enjoyment: (sum{p in P, d in D, j in J} A[p,j,d] * (L[p, j] * WL - H[p, j] * WH)) - sum{p in P} error[p];
solve;
printf "Sum %d\n", (sum{p in P, d in D, j in J} A[p,j,d] * (L[p, j] * WL - H[p, j] * WH));
printf "p d j W l\n";
printf ">>>>\n";
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,d] * (L[p, j] * WL - H[p, j] * WH), Wl[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;
data;
/* Test example */
param P_count := 44;
param J_count := 11;
param D_count := 3;
param WL := 1;
param WH := 3;
param Wl := 1 4, 2 4, 3 2, 4 2, 5 4, 6 3, 7 2, 8 1, 9 1, 10 2, 11 2;
# de pol-parameter
param max_load := 25,1,2; # 12,1,0 12,2,0 12,3,0;
param R : 1 2 3 4 5 6 7 8 9 10 11 :=
1 1 3 0 0 1 3 4 6 2 5 0
2 1 0 6 4 1 3 4 6 2 5 5
3 1 0 0 0 1 3 4 6 2 5 5;
/* AUTOGEN STARTS HERE */
param L : 5 6 7 8 9 10 :=
1 0 1 0 1 0 0
2 0 0 1 1 0 1
3 0 0 1 0 0 1
6 0 1 0 0 0 1
7 0 0 0 1 0 1
8 0 1 0 0 1 0
9 0 1 1 0 0 1
11 1 0 0 1 0 0
13 0 1 0 0 1 0
14 0 1 0 0 0 1
16 0 1 0 0 0 0
18 1 0 0 0 0 0
19 0 0 1 0 1 1
20 0 0 0 0 0 1
21 0 0 0 1 1 0
22 0 1 1 0 0 1
23 0 1 0 1 0 0
24 0 0 0 0 1 0
25 1 0 0 0 0 0
26 0 1 1 0 0 1
27 0 1 0 0 0 1
28 0 1 0 1 0 0
29 0 0 1 1 0 0
30 0 1 1 0 0 0
31 0 1 0 0 0 0
32 0 0 1 0 1 1
34 0 0 0 0 1 1
35 0 1 0 1 1 0
36 0 1 0 0 0 1
38 0 0 1 0 1 1
39 0 0 1 0 0 1
40 0 1 0 0 0 1
41 0 1 1 0 0 1
43 0 1 0 0 0 0
44 0 0 0 1 0 0;
param H : 6 7 8 9 10 :=
1 0 0 0 0 1
2 1 0 0 1 0
6 0 1 0 0 0
7 0 1 0 0 0
8 0 1 1 0 0
9 0 0 1 0 0
11 0 1 0 1 0
13 0 1 1 0 0
14 0 0 1 1 0
16 0 0 0 0 1
18 0 1 0 0 1
19 1 0 1 0 0
21 1 1 0 0 0
22 0 0 1 1 0
23 0 1 0 0 0
24 0 0 1 0 0
25 0 1 0 0 0
26 0 0 1 0 0
27 0 0 1 0 0
28 0 1 0 1 0
29 0 0 0 0 1
30 0 0 0 1 0
31 0 0 0 1 0
32 1 0 1 0 0
34 0 0 1 0 0
35 0 1 0 0 1
36 0 1 0 1 0
38 1 0 1 0 0
39 1 0 1 0 0
40 0 0 0 1 0
41 0 0 1 1 0;
param C : 1 2 3 5 6 9 :=
1 0 0 0 0 1 0
2 0 1 0 0 0 0
3 0 0 0 0 0 0
4 1 0 0 0 0 0
5 1 0 1 0 0 0
6 0 1 0 0 1 0
7 0 0 0 0 0 0
8 0 0 0 0 1 1
9 1 0 0 0 1 0
10 0 0 0 0 0 0
11 0 0 0 1 0 0
12 1 0 0 0 0 0
13 1 0 0 0 1 1
14 0 0 0 0 1 0
15 0 0 0 0 0 0
16 0 0 0 0 1 0
17 0 0 0 0 0 0
18 0 0 0 1 0 0
19 0 0 0 0 0 1
20 0 0 0 0 0 0
21 0 0 1 0 0 1
22 0 0 0 0 1 0
23 0 0 0 0 1 0
24 0 0 1 0 0 1
25 0 1 0 1 0 0
26 0 0 0 0 1 0
27 0 0 0 0 1 0
28 0 0 0 0 1 0
29 0 0 0 0 0 0
30 0 0 0 0 1 0
31 0 0 1 0 1 0
32 0 0 0 0 0 1
33 0 0 0 0 0 0
34 0 0 0 0 0 1
35 0 0 0 0 1 1
36 0 0 0 0 1 0
37 0 0 0 0 0 0
38 0 0 0 0 0 1
39 0 0 0 0 0 0
40 0 0 0 0 1 0
41 0 0 0 0 1 0
42 0 0 0 0 0 0
43 0 0 1 0 1 0
44 0 0 1 0 0 0;
param Q := 5,1,1,1 25,5,1,1 18,5,2,1 11,5,3,1;
end;

112
config.yaml Normal file
View File

@ -0,0 +1,112 @@
config:
days: 3
weights:
likes: 1
hates: 3
# TODO: load_dev
ignore: ["(vega)"]
task_re: "[ ,/]+"
tasks:
hotemetoten:
personen: [Linda, Yorick, avel]
workload: 4
req: [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
superkok:
req: [1, 1, 1]
personen: [macgyver, bas, lucus]
workload: 4
hardcode:
- macgyver # dag 1
- bas # dag 2
- lucus # dag 3
lookup: [superkok]
koken:
req: [3, 3, 3]
workload: 3
personen: liefhebbers
lookup: [koken, kookhulp]
schoonmaken:
req: [4, 4, 4]
workload: 2
personen: iedereen
lookup: [schoonmaken]
snackdealen:
req: [6, 6, 6]
workload: 1
personen: iedereen
lookup: [hapjes]
fotograferen:
req: [2, 2, 2]
workload: 1
personen: liefhebbers
lookup: [fotograferen, fototroep]
afwassen:
req: [5, 5, 5]
workload: 2
personen: iedereen
lookup: [afwassen]
snijpieten:
req: [0, 5, 5]
workload: 2
personen: iedereen
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
- Wassasin
- Abel
- ElizaAntoine
- carrot
- eric s
- Mike Koeman
- Joshua
- Tessa

22
glpm.py Normal file
View File

@ -0,0 +1,22 @@
def col_all_zeros(ls, i, al=0):
return all(x[i] == al for x in ls)
def row_all_zeros(ls, i, al=0):
return all(x == al for x in ls[i])
def matrix(name, ls, default=0):
nonzero_cols = [i+1 for i in range(len(ls[0])) if not col_all_zeros(ls, i, default)]
nonzero_rows = [i+1 for i in range(len(ls)) if not row_all_zeros(ls, i, default)]
res = ""
for r in nonzero_rows:
res += "\n{:2d}".format(r)
for c in nonzero_cols:
res += " {:2d}".format(ls[r-1][c-1])
return param(name, res, " : " + " ".join("{:2d}".format(x) for x in nonzero_cols))
def dict(name, thing, default=None):
fmt_key = lambda k: " ".join((str(x+1) for x in k)) if type(k) == tuple else k+1
return param(name, ", ".join(["{} {}".format(fmt_key(k), v) for k,v in thing.items() if v != default]))
def param(name, val, middle=""):
val = str(val)
if "\n" in val:
val = val.replace("\n", "\n" + " " * (len(name) + 6))
return "param {}{} := {};".format(name, middle, val)

155
magisch_corvee_script.py Executable file
View File

@ -0,0 +1,155 @@
#! /usr/bin/env nix-shell
#!nix-shell -i python3 -p python python3Packages.pyyaml glpk
import sys
import yaml
import re
import subprocess
from collections import OrderedDict
import glpm
class Person(object):
def __init__(self, conf={}):
self.can = set()
self.loves = set()
self.hates = set()
self.does = set() # hardcoded
self.has_prefs = False
self.conf = conf
def vrolijkheid(self):
res = config['days'] - len(self.does)
for (d,t) in self.does:
if t in self.loves:
res += config['weights']['likes']
if t in self.hates:
res -= config['weights']['hates']
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 read_people(conf_ppl):
def isdict(x):
return type(x) == dict
people = OrderedDict()
for x in conf_ppl:
val = {}
if type(x) == dict:
x,val = x.popitem()
people[x.lower()] = Person(val)
return people
# deal with loves/hates
def make_task_lut(tasks):
task_lut = {}
for t, taskconf in tasks.items():
if 'lookup' in taskconf:
for lookup in taskconf['lookup']:
task_lut[lookup] = t
task_re = re.compile(config['task_re'])
def lookup_tasks(tasks):
return (task_lut[x] for x in task_re.split(tasks) if not x in config['ignore'])
return lookup_tasks
def read_prefs(pref_file, tasks, people):
lookup_tasks = make_task_lut(tasks)
# read the wiki corvee table
for [name, loves, hates] in ((q.strip().lower() for q in x.split('\t')) for x in pref_file):
p = people[name]
p.has_prefs = True
p.loves |= set(lookup_tasks(loves))
p.hates |= set(lookup_tasks(hates))
for name, p in people.items():
if not p.has_prefs:
print("warning: no preferences for", name, file=sys.stderr)
# deal with capability and hardcode
def set_capabilities(tasks, people):
for ti,(task,conf) in enumerate(tasks.items()):
if conf['personen'] == 'iedereen':
for p in people.values():
p.can.add(task)
elif conf['personen'] == 'liefhebbers':
for p in people.values():
if task in p.loves:
p.can.add(task)
else:
for p in conf['personen']:
people[p.lower()].can.add(task)
if 'hardcode' in conf:
for day, pers in enumerate(conf['hardcode']):
people[pers.lower()].does.add((day, task))
# format as matrices
def matrices(people, tasks):
mat = lambda a,b: [[0 for j in b] for i in a]
loves = mat(people, tasks)
hates = mat(people, tasks)
capab = mat(people, tasks)
tsk_idx = index(tasks)
hardcode = {}
max_loads = {}
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
for t in p.can: capab[i][tsk_idx[t]] = 1
for (d,t) in p.does: hardcode[(i,tsk_idx[t],d)] = 1
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
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]
def read_assignment(file, people, tasks):
def between_the_lines(f, a=">>>>\n", b="<<<<\n"):
for l in f:
if l == a: break
for l in f:
if l == b: break
yield map(int, l.strip().split())
for p in people.values():
p.does = set()
person_vl = list(people.values())
task_nm = list(tasks.keys())
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)
print(glpm.matrix("L", loves), file=file)
print(glpm.matrix("H", hates), file=file)
print(glpm.matrix("C", capab, 1), file=file)
print(glpm.matrix("R", req, None), file=file)
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.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)
print(glpm.param("WL", config['weights']['likes']), file=file)
print(glpm.param("WH", config['weights']['hates']), file=file)
def write_tasks(people, tasks, file=sys.stdout):
for name, p in people.items():
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("|-")
people = read_people(conf['people'])
with open('prefs_table', 'r') as pref_file:
read_prefs(pref_file, tasks, people)
set_capabilities(tasks, people)
if len(sys.argv)>1 and sys.argv[1] == 'in':
write_data(people, tasks)
elif len(sys.argv)>1 and sys.argv[1] == 'out':
with open('output', 'r') as out_file:
read_assignment(out_file, people, tasks)
write_tasks(people, tasks)
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)
with open('output', 'r') as file:
read_assignment(file, people, tasks)
write_tasks(people, tasks)

78
model.glpm Normal file
View File

@ -0,0 +1,78 @@
/* Number of people */
param P_count, integer, > 0;
/* Number of jobs */
param J_count, integer, > 0;
/* Number of days */
param D_count, integer, > 0;
param WL, integer, > 0;
param WH, integer, > 0;
set P := 1..P_count;
set J := 1..J_count;
set D := 1..D_count;
/* Person p likes to solve jobs j */
param L{p in P, j in J} default 0, binary;
/* Person p hates to solve jobs j */
param H{p in P, j in J} default 0, binary;
/* Person p is capable to perform job j */
param C{p in P, j in J} default 1, binary;
/* How many jobs need to be done on what day */
param R{d in D, j in J}, integer, >= 0;
/* hardcoded */
param Q{p in P, j in J, d in D}, default 0, binary;
/* workload */
param Wl{j in J}, integer, >= 0;
param max_load{p in P, d in D}, default 1, integer;
/* Person p is allocated to do job j on day d */
var A{p in P, j in J, d in D}, binary;
var error{p in P}, integer, >= 0;
s.t. hardcode{p in P, j in J, d in D}: A[p,j,d] >= Q[p,j,d];
/* A person only has one task per day, at most */
s.t. max_load_person{p in P, d in D}: sum{j in J} A[p,j,d] <= max_load[p,d];
/* A person has at least D-1 tasks */
#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;
/* 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];
/* 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]);
/* Maximize enjoyment */
# minimize error_diff: sum{p in P} error[p];
maximize enjoyment: (sum{p in P, d in D, j in J} A[p,j,d] * (L[p, j] * WL - H[p, j] * WH)) - sum{p in P} error[p];
solve;
printf "Sum %d\n", (sum{p in P, d in D, j in J} A[p,j,d] * (L[p, j] * WL - H[p, j] * WH));
printf "p d j W l\n";
printf ">>>>\n";
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,d] * (L[p, j] * WL - H[p, j] * WH), Wl[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;
end;

35
prefs_table Normal file
View File

@ -0,0 +1,35 @@
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

View File

@ -1,112 +0,0 @@
lovehate = dict((x.split('\t')[0].lower(), [q.strip() for q in x.split('\t')[1:]]) for x in open('table'))
people = list(x.strip().lower() for x in open('people'))
used = 0
for person in people:
try:
assert(len(lovehate[person]) == 2)
used += 1
except KeyError:
print("unable to match up", person)
except AssertionError:
print("wrong lovehate", person, lovehate[person])
raise
assert(used == len(lovehate.keys()))
import yaml
conf = yaml.load(open('tasks', 'r'))
config = conf['config']
tasks_dict = conf['tasks']
# print(tasks_dict)
tasks = list(tasks_dict.keys())
tasksi = dict(((v,k) for k,v in enumerate(tasks)))
peoplei = dict(((v,k) for k,v in enumerate(people)))
tasksdesc = {
"schoonmaken": ['schoonmaken'],
"afwassen": ['afwassen'],
"koken": ['koken', 'kookhulp'],
"snackdealen": ['hapjes'],
"ignore": ['(vega)', '(liever niet dezelfde maaltijd als het kan)', ''],
"superkok": ['superkok'],
"fotograferen": ['fotograferen', 'fototroep']
}
tasksdesci = {}
import re
for t,a in tasksdesc.items():
for q in a: tasksdesci[q] = t
loves_matrix = [[0] * len(tasks) for person in people]
hates_matrix = [[0] * len(tasks) for person in people]
capab_matrix = [[0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1] for person in people]
def set_capab(person, task):
capab_matrix[peoplei[person]][tasksi[task]] = 1
cake_penalty = ["linda", "nanette", "alphacentauri", "obfusk (felix)", "tessa", "joshua"]
for person,(loves, hates) in lovehate.items():
loves = [tasksdesci[x] for x in re.split('[ ,/]+', loves) if tasksdesci[x] != 'ignore']
hates = [tasksdesci[x] for x in re.split('[ ,/]+', hates) if tasksdesci[x] != 'ignore']
for l in loves:
loves_matrix[peoplei[person]][tasksi[l]] = 1
set_capab(person, l)
for h in hates: hates_matrix[peoplei[person]][tasksi[h]] = 1
for person in cake_penalty:
set_capab(person, "baktaarten")
for person in ["macgyver", "colin", "petervdv"]:
set_capab(person, "halen")
set_capab("weasel", "hotemetoten")
set_capab("yorick", "hotemetoten")
set_capab("linda", "hotemetoten")
#capab_matrix[peoplei["avel"]] = [0]*len(tasks)
def col_all_zeros(ls, i, al=0):
return all(x[i] == al for x in ls)
def row_all_zeros(ls, i, al=0):
return all(x == al for x in ls[i])
def format_matrix(name, ls, default=0):
nonzero_cols = [i+1 for i in range(len(ls[0])) if not col_all_zeros(ls, i, default)]
nonzero_rows = [i+1 for i in range(len(ls)) if not row_all_zeros(ls, i, default)]
print("param", name, ":", " ".join("{:2d}".format(x) for x in nonzero_cols), ":=")
for r in nonzero_rows:
print("{:9d}".format(r), end='')
for c in nonzero_cols:
print(" {:2d}".format(ls[r-1][c-1]), end='')
print(';' if r == nonzero_rows[-1] else '')
def format_dict(name, thing, default=None):
print("param {} := {};".format(name, ", ".join(["{} {}".format(k, v) for k,v in thing.items() if v != default])))
def format_param(name, val):
print("param {} := {};".format(name, val))
req_matrix = [[tasks_dict[t]['req'][d] for t in tasks] for d in range(config['days'])]
from collections import defaultdict
import sys
if sys.argv[1] == 'in':
format_matrix("L", loves_matrix)
format_matrix("H", hates_matrix)
format_matrix("C", capab_matrix, 1)
format_matrix("R", req_matrix, None)
# hardcode: superkoks, linda hotemetoot
print("param Q := 5,1,1,1 25,5,1,1 18,5,2,1 11,5,3,1;")
format_dict("Wl", {tasksi[t]+1: tasks_dict[t]['workload'] for t in tasks})
format_param("D_count", config['days'])
format_param("P_count", len(people))
format_param("J_count", len(tasks))
format_param("WL", config['weights']['likes'])
format_param("WH", config['weights']['hates'])
elif sys.argv[1] == 'out':
flag=False
ln = []
for l in open('output'):
if l == "<<<<\n":
flag = False
if flag:
ln.append(map(int, l.strip().split()))
if l == ">>>>\n":
flag=True
assigned = defaultdict(lambda: [[], [], []]) # lambda: [("", 1, 0), ("", 1, 0), ("", 1, 0)])
for [p, d, j, W, l] in ln:
assigned[people[p-1]][d-1].append((tasks[j-1], W, l))
for p, (a, b, c) in assigned.items():
q = lambda w: ",".join([x[0] + " <3" if x[1] else x[0] for x in w])
v = lambda w: sum([x[1] for x in w]) if len(w) else 1
l = lambda w: sum([x[2] for x in w])
print("| {} || {} || {} || {} || {}||{}".format(p, q(a), q(b), q(c), v(a)+v(b)+v(c), l(a)+l(b)+l(c)))
print("|-")
else:
print(sys.argv[0], "in|out")