I am trying to add a constraint to a mixed integer programming model in R so that each person is only assigned to a single role.
I have a data frame that looks like this:
ID Name Role PreferenceScore
----- ------- --------- ------------------
1 Abby Chef 10
1 Abby Waiter 8
1 Abby Greeter 9
2 Bob Chef 7
2 Bob Waiter 8
2 Bob Greeter 3
3 Carly Chef 5
3 Carly Waiter 8
3 Carly Greeter 4
... ... ... ...
20 David Chef 2
20 David Waiter 3
20 David Greeter 8
I am trying to assign each person to a role based on their preferences (larger number is better) using MIPmodel. Each role can have up to 8 people, and there are 20 total people in total.
Here is what I have so far:
library(dplyr)
library(ompr)
library(ompr.roi)
library(ROI)
library(ROI.plugin.glpk)
teamData <- read.csv("filename")
teamData$wait <- if_else(teamData$jobType == "Waiter", 1, 0)
teamData$chef <- if_else(teamData$jobType == "Chef", 1, 0)
teamData$greet <- if_else(teamData$jobType == "Greeter", 1, 0)
p <- nrow(teamData)
v <- as.numeric(teamData$PreferenceScore)
maxTeamSize <- 8
role <- teamData$Role
chef_job <- teamData$chef
waiter_job <- teamData$wait
greeter_job <- teamData$greet
name <- teamData$Name
# Build the model
model <- MIPModel() %>%
add_variable(x[i], i=1:p, type = "binary") %>%
set_objective(sum_expr(x[i] * v[i], i=1:p)) %>%
add_constraint(sum_expr(chef_job[i], i=1:p) <= 8) %>%
add_constraint(sum_expr(waiter_job[i], i=1:p) <= 8) %>%
add_constraint(sum_expr(greeter_job[i], i=1:p) <= 8) # %>%
# add_constraint(sum_expr(count(name[i])) == 1)
solved <- solve_model(model, with_ROI("glpk"))
result <- solved %>%
get_solution(x[i]) %>%
select(i) %>%
rowwise() %>%
mutate(Pref = v[i], Role = role[i], teamData$Name[i]) %>%
ungroup
result
My main problem right now is that I can't figure out how to add a constraint so that each person only has one role in the solution (i.e. each person can only be either a chef, waiter, or greeter)
Any pointers would be greatly appreciated.
This is a typical assignment problem where you are assigning person
p
to jobj
. So, you need to update your formulation to have a double indexed decision variable,x[p, j]
. Then things will start to make more sense... :).You can then sum across all jobs to ensure each person has no more than one assignment (in pseudocode... my R syntax is terrible):
and you can make make sure no position is overfilled if you have a maximum of
spots[j]
fills in each role:and your objective function will fall into place similarly by multiplying by
preference[p, j]