---
title: "PhD Workload Allocation"
output: 
  rmarkdown::html_vignette:
    toc: true
    toc_depth: 2
vignette: >
  %\VignetteIndexEntry{PhD Workload Allocation}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

# Model introduction

Consider a situation where a department needs to allocate semester workload
across PhD students. Let there be $N_s$ students indexed by
$i \in \{1,\ldots,N_s\}$ and $N_j$ courses indexed by
$j \in \{1,\ldots,N_j\}$. For each course-role pair, where
$r \in \{\mathrm{TA}, \mathrm{GR}, \mathrm{E}\}$, the required demand
$d_{j,r}$ must be fully assigned.

For each student-course pair, $P_{i,j}$ denotes the TA preference score.
Student seniority is represented by $s_i$, where Year-1, Year-2, Year-3 and
Year-4 are mapped to $-1,0,1,2$ respectively. We also track prior-semester TA
and GR workload, denoted by $t_i^{(1)}$ and $g_i^{(1)}$.

This model allocates current-semester TA, GR and E units while balancing:

1.  TA fairness across non-Year-1 students,
2.  TA preference satisfaction,
3.  Seniority-aware E allocation, and
4.  protection of Year-1 students from excessive TA load.

# Objective function

The model minimises the weighted objective:

\begin{align*}
X_{i,j,r} &\in \mathbb{Z}_{\ge 0} && \text{units of role } r \text{ in course } j \text{ assigned to student } i \\
t_i^{(2)} &= \sum_{j=1}^{N_j} X_{i,j,\mathrm{TA}} && \text{current-semester TA workload} \\
g_i^{(2)} &= \sum_{j=1}^{N_j} X_{i,j,\mathrm{GR}} && \text{current-semester GR workload} \\
e_i^{(2)} &= \sum_{j=1}^{N_j} X_{i,j,\mathrm{E}} && \text{current-semester E workload} \\
T_i &= t_i^{(1)} + t_i^{(2)} && \text{yearly TA workload} \\
G_i &= g_i^{(1)} + g_i^{(2)} && \text{yearly GR workload} \\
w_i &\ge 0 && \text{slack for Year-1 TA soft bound} \\
T_{\max} &\ge 0 && \text{maximum yearly TA workload among students with } s_i \ge 0 \\
T_{\min} &\ge 0 && \text{minimum yearly TA workload among students with } s_i \ge 0
\end{align*}

$$
\min \quad
\alpha (T_{\max} - T_{\min})
- \beta \sum_{i=1}^{N_s} \sum_{j=1}^{N_j} P_{i,j} X_{i,j,\mathrm{TA}}
- \phi \sum_{i=1}^{N_s} \sum_{j=1}^{N_j} s_i X_{i,j,\mathrm{E}}
+ \rho \sum_{i:s_i=-1} w_i
$$

where $\alpha,\beta,\phi,\rho \ge 0$ are user-specified weights.

# Constraints

## Demand satisfaction

For every course and role, assigned units must match demand:

$$
\sum_{i=1}^{N_s} X_{i,j,r} = d_{j,r},
\quad \forall j,\; r \in \{\mathrm{TA}, \mathrm{GR}, \mathrm{E}\}
$$

## TA spread among non-Year-1 students

The spread term applies only to students with $s_i \ge 0$:

\begin{align}
T_i &\le T_{\max}, \quad \forall i : s_i \ge 0 \\
T_i &\ge T_{\min}, \quad \forall i : s_i \ge 0
\end{align}

## Annual workload equality

Let $C$ denote semester workload capacity per student. The model fixes each
student's annual workload total at $2C$.

$$
T_i + G_i + e_i^{(2)} = 2C, \quad \forall i
$$

## Year-1 TA soft upper bound

For Year-1 students, current-semester TA load is softly capped:

$$
t_i^{(2)} \le t_{\max}^{(Y1)} + w_i, \quad \forall i : s_i = -1
$$

## Optional current-semester workload bounds

If provided by the user, the following bounds are imposed:

\begin{align}
t_{\min}^{(2)} \le t_i^{(2)} \le t_{\max}^{(2)}, \quad \forall i \\
g_{\min}^{(2)} \le g_i^{(2)} \le g_{\max}^{(2)}, \quad \forall i \\
e_{\min}^{(2)} \le e_i^{(2)} \le e_{\max}^{(2)}, \quad \forall i
\end{align}

If any bound parameter is omitted, the corresponding constraint is not added.
