-
Notifications
You must be signed in to change notification settings - Fork 0
/
scheduler.py
executable file
·145 lines (132 loc) · 4.39 KB
/
scheduler.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
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
#!/usr/bin/env python
# vim: set ft=python :
import argparse
from pathlib import Path
import networkx as nx
import structlog
from model import Model
from structlog_config import Level, LevelName, Renderer, configure_structlog
from structlog_processors import graph_transformer
THIS_FILE = Path(__file__)
logger = structlog.get_logger(__name__)
def main(
*,
participant_adjlist,
participant_excluded,
solution_dir,
desired_group_size,
historical_solution_limit,
solution_limit,
):
log = logger.bind()
participant_graph = nx.read_adjlist(
participant_adjlist,
create_using=nx.DiGraph,
)
log.debug("participants", graph=participant_graph)
participant_excluded_graph = nx.read_adjlist(
participant_excluded,
)
log.debug("excluded", graph=participant_excluded_graph)
for node in participant_excluded_graph:
participant_graph.remove_node(node)
log.debug("participants - excluded", graph=participant_graph)
model = Model(
participant_graph=participant_graph,
desired_group_size=desired_group_size,
solution_dir=solution_dir,
historical_solution_limit=historical_solution_limit,
)
model.solve(solution_limit=solution_limit)
if __name__ == "__main__":
parser = argparse.ArgumentParser(
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
parser.add_argument(
"--participant-adjlist",
type=Path,
default=THIS_FILE.with_name("participant-adjlist"),
help=(
"participants in NetworkX's adjacency list format; "
"managers should have edges to their direct reports to "
"avoid grouping managers with their direct reports in the "
"solution: "
"https://networkx.org/documentation/stable/reference/readwrite/adjlist.html"
),
)
parser.add_argument(
"--participant-excluded",
type=Path,
default=THIS_FILE.with_name("participant-excluded"),
help=(
"participants to be excluded from the solution; useful "
"when someone is out of office (one participant per line)"
),
)
parser.add_argument(
"--solution-dir",
type=Path,
default=THIS_FILE.with_name("solutions"),
help=(
"directory to which the solution will be written and from "
"which historical solutions may be read (solution files "
"have one space-delimited group per line)"
),
)
parser.add_argument(
"--desired-group-size",
type=int,
default=2,
help="desired size of each group in the solution (must not be less than 2)",
)
parser.add_argument(
"--historical-solution-limit",
type=int,
default=None,
help=(
"max number N of most recent historical solutions to "
"account for when generating the next solution; if two "
"participants were in the same group in any of the N most "
"recent historical solutions, they will not be assigned to "
"the same group (None makes N infinite, 0 disables this "
"constraint"
),
)
parser.add_argument(
"--solution-limit",
type=int,
default=1,
help=(
"max number N of solutions to generate; this option is "
"primarily for exploratory purposes and should normally be "
"set to 1"
),
)
parser.add_argument(
"--log-min-level",
type=LevelName,
default=LevelName.INFO,
choices=list(LevelName),
help="only process log records at this level or greater",
)
parser.add_argument(
"--log-renderer",
type=Renderer,
default=Renderer.AUTO,
choices=list(Renderer),
help=f'auto: "{Renderer.CONSOLE}" if stdout is a TTY, otherwise "{Renderer.JSON}"',
)
args = parser.parse_args()
configure_structlog(
min_level=Level[args.log_min_level],
processors=[graph_transformer],
renderer=args.log_renderer,
)
main(
participant_adjlist=args.participant_adjlist,
participant_excluded=args.participant_excluded,
solution_dir=args.solution_dir,
desired_group_size=args.desired_group_size,
historical_solution_limit=args.historical_solution_limit,
solution_limit=args.solution_limit,
)