|
1 | 1 | # Teamformer |
2 | 2 |
|
3 | | - |
4 | | -Teamformer builds student teams for you. The primary objective is to form as few teams as are needed while ensuring constraints are met, and encouraging WAM (weighted average mark/gpa) balance across teams. The system is basically a wrapper around a CP-SAT solver using Google OR-Tools. |
| 3 | +Teamformer builds student teams for you. The primary objective is to form as few teams as are needed while ensuring constraints are met, and encouraging WAM (weighted average mark/GPA) balance across teams. The system is a wrapper around a CP-SAT solver using Google OR-Tools. |
5 | 4 |
|
6 | 5 | Constraint handling includes: |
7 | 6 |
|
8 | | -✅ Each student is assigned to exactly one team |
| 7 | +✅ Each student is assigned to exactly one team |
9 | 8 |
|
10 | 9 | ✅ Each team has between min and max students |
11 | 10 |
|
12 | | -✅ No team has only one student of a given gender (current only M/F, if other self-report categories these are ignored and not balanced, but does not break anything) |
| 11 | +✅ No team has only one student of a given gender (currently only M/F; other self-reported categories are ignored for balancing, but won't break anything) |
13 | 12 |
|
14 | 13 | ✅ The number of teams used is minimized |
15 | 14 |
|
16 | 15 | ✅ Students are only assigned to teams in the same lab as them |
17 | 16 |
|
18 | | -✅ Deviation from average WAM across class is penalised |
| 17 | +✅ Deviation from average WAM across the class is penalised |
| 18 | + |
| 19 | +✅ Student preferences are favoured (positive and negative preferences now supported!) |
19 | 20 |
|
20 | | -❌ Student preferences are favoured (Not yet implemented) |
| 21 | +The output is an Excel sheet with students and teams. Team numbers may not be sequential (drawn from 1\:max\_teams). |
21 | 22 |
|
22 | | -The output is an excel sheet with students and teams. Team numbers may not be sequential (drawn from 1:max_teams). |
| 23 | +--- |
23 | 24 |
|
24 | 25 | ### Data structure |
25 | | -Team former assumes data is in a spreadsheet that looks something like (fake data): |
26 | 26 |
|
27 | | -| | first_name | last_name | email | gender | wam | lab | |
28 | | -|---:|:-------------|:------------|:--------------------------|:---------|------:|------:| |
29 | | -| 0 | Mark | Johnson | ... | M | 51.13 | 3 | |
30 | | -| 1 | Donald | Walker | ... | M | 60.04 | 1 | |
31 | | -| 2 | Sarah | Rhodes | ... | F | 76.57 | 1 | |
32 | | -| 3 | Steven | Miller | ... | M | 54.22 | 2 | |
33 | | -| 4 | Javier | Johnson | ... | M | 75.26 | 4 | |
| 27 | +Teamformer expects data in a spreadsheet like this (fake example): |
| 28 | + |
| 29 | +| | first\_name | last\_name | email | gender | wam | lab | Prefer\_With | Prefer\_Not\_With | |
| 30 | +| - | ----------- | ---------- | ----- | ------ | ---- | --- | ------------ | ----------------- | |
| 31 | +| 0 | Mark | Johnson | ... | M | 51.1 | 3 | S2, S3 | S4 | |
| 32 | +| 1 | Donald | Walker | ... | M | 60.0 | 1 | | | |
| 33 | +| 2 | Sarah | Rhodes | ... | F | 76.6 | 1 | S1 | S3 | |
| 34 | +| 3 | Steven | Miller | ... | M | 54.2 | 2 | | | |
| 35 | +| 4 | Javier | Johnson | ... | M | 75.3 | 4 | | | |
| 36 | + |
| 37 | +**Columns used:** |
| 38 | + |
| 39 | +* `gender` |
| 40 | +* `wam` |
| 41 | +* `lab` |
| 42 | +* `Prefer_With` (optional): comma-separated list of Student\_IDs the student wants to work with |
| 43 | +* `Prefer_Not_With` (optional): comma-separated list of Student\_IDs the student prefers not to work with |
34 | 44 |
|
35 | | -**Only the gender, wam and lab columns are used.** |
| 45 | +--- |
36 | 46 |
|
37 | 47 | ### Install |
38 | 48 |
|
39 | | -``` |
| 49 | +```bash |
40 | 50 | pip install -e . |
41 | 51 | ``` |
| 52 | + |
| 53 | +--- |
| 54 | + |
42 | 55 | ### Run |
43 | 56 |
|
44 | | -``` |
45 | | -team_former --input_file=students.xlsx --sheet_name=0 --output_file=teams.xlsx --wam_weight=0.05 --min_team_size=3 --max_team_size=5 --max_solve_time=30 |
| 57 | +```bash |
| 58 | +team_former --input_file=students.xlsx --sheet_name=0 --output_file=teams.xlsx --wam_weight=0.05 --pos_pref_weight=0.8 --neg_pref_weight=0.8 --min_team_size=3 --max_team_size=5 --max_solve_time=30 |
46 | 59 | ``` |
47 | 60 |
|
| 61 | +--- |
| 62 | + |
48 | 63 | ### How to get a good solution |
49 | 64 |
|
50 | 65 | Depending on your class sizes, demographics and lab distribution, you may struggle to find a feasible solution. Options to address this include: |
51 | | -* Increase the max solve time, it may just be a matter of waiting a bit longer |
52 | | -* Reduce or remove the wam weight penalty |
53 | | -* Reduce the minimimun team size, it may be that the balance of students is infeasible. |
| 66 | + |
| 67 | +* Increase the max solve time — it may just be a matter of waiting longer |
| 68 | +* Reduce or remove the WAM weight penalty |
| 69 | +* Adjust the minimum team size — sometimes team balance is infeasible |
| 70 | +* Adjust positive or negative preference weights (e.g., set `pos_pref_weight=0.5` if you want preferences to have less influence) |
| 71 | + |
| 72 | +--- |
| 73 | + |
| 74 | +### Preference handling |
| 75 | + |
| 76 | +When using preference columns, Teamformer will attempt to: |
| 77 | + |
| 78 | +* **Keep students together** if listed in `Prefer_With`, unless it conflicts with other constraints. |
| 79 | +* **Avoid assigning students together** if listed in `Prefer_Not_With`. |
| 80 | + |
| 81 | +Preferences are not strictly enforced (they are "soft" constraints), but they strongly influence the solution when weights are set high. |
| 82 | + |
| 83 | +--- |
0 commit comments