1

In a given hour, I have a set of tasks that need to be completed and the time it takes for completion of each. This could be, for example:

Task Time to complete (hrs)
A 0.2
B 0.25
C 0.1
D 0.5
E 0.5
F 0.5

Assume I have infinite resource/persons to assign to tasks. I am looking to find a method of completing all tasks in the above table, which assigns the least possible persons.

Since the tasks take 2.05 hours to complete in total, if there are no constraints this solution is easy (i.e. ceiling(2.05) = 3, where ceiling() is the ceiling function). However I have a set of constraints which tell me what the permissible combinations of tasks are:

Task
A
B
C
D
E
F
A, B
A, C
B, C
A, B, C
D, E
D, F

That is, in one hour, a person can only do the above tasks/combinations of tasks and NOT others, e.g. doing E and F in the same hour is impermissible.

Edit: When giving one person a combination of tasks, the amount of time this person contributes toward the completion of each task must add up to at most (less than or equal to) an hour. For example, giving one person A, B, C means they can do x, y, z hrs of A, B, C respectively, where x, y, z are free to choose but subject to the constraint x + y + z <= 1.

Obviously this complicates the problem and whilst it is easy to solve intuitively I'm not sure if there is an efficient algorithm for this sort of problem, or pre-built functions/packages in R.

Thanks

Elis
  • 70
  • 10

1 Answers1

3

Assuming that the problem is to select the minimum number of rows from the second data frame such that each task is done once then the first data frame is irrelevant so we can formulate the following integer linear program (known as a set partitioning problem) such that M[i, j] is 1 if the ith task is in the jth row of DF (where DF is shown in Note at end) and x is a 0/1 vector ncol(M) long to be solved for.

minimize 1'x s.t. Mx = 1 and x[j] is in {0,1} for all j

or in R code

library(lpSolve)

s <- strsplit(gsub(" ", "", DF$Task), ",")
names(s) <- seq_along(s)
stk <- stack(s)
M <- table(stk)

res <- lp("min", rep(1, ncol(M)), M, "==", rep(1, nrow(M)), all.bin = TRUE)
res
## Success: the objective function is 3 

res$solution
## [1] 0 0 0 0 1 0 0 0 0 1 0 1

bin2name <- function(x) rownames(M)[x == 1]
apply(M[, res$solution == 1, drop = FALSE], 2, bin2name)
## $`5`
## [1] "E"
##
## $`10`
## [1] "A" "B" "C"
##
## $`12`
##  [1] "D" "F"

Note

Lines <- "Task
A
B
C
D
E
F
A,B
A,C
B,C
A,B,C
D,E
D,F"
DF <- read.table(text = Lines, header = TRUE, strip.white = TRUE)
G. Grothendieck
  • 254,981
  • 17
  • 203
  • 341
  • Thanks for the response. However what about a case where e.g. the first data frame shows 0.7hrs time to complete task A? In this case we get the same answer, and are told that one person on A, B, C for an hour is enough to cover the demands 0.7hrs, 0.25hrs, 0.1hrs respectively. But 0.7 + 0.25 + 0.1 = 1.05hrs > 1hr, so this is 0.05hrs that we still need to cover. – Elis Jul 15 '22 at 14:22
  • As the question is stated the hours are not involved. If you want them involved please fix the question to clearly state what the objective and what the constraints are. – G. Grothendieck Jul 15 '22 at 14:28
  • I have added to the question to make this constraint clear. – Elis Jul 15 '22 at 14:48
  • IF what you mean is that for each row of DF we get the corresponding hours from the first table in the question and add them and remove that row from DF if they don't sum to 1 then only the last two rows of DF satisfy that so the answer does not exist. – G. Grothendieck Jul 15 '22 at 17:06
  • Sorry, I didn't formulate the constraint correctly. I meant to say that the total hours for one person must be at most 1, or that x + y + z <= 1, for a task/combination to be valid. – Elis Jul 17 '22 at 19:27
  • All the rows of the first data frame satisfy that constraint so the constraint does not add anything. – G. Grothendieck Jul 18 '22 at 12:45
  • I know that, this was an example data frame, and so for example A could take value 0.7hrs as in my first comment, so there is a need to check this constraint as there is no guarantee that it adds nothing – Elis Jul 18 '22 at 12:48
  • Just remove the columns of M that don't satisfy the constraint and then use the solution already provided. If Hours if the first data frame in the question then `M <- M[, colSums(M * Hours[[2]]) <= 1]` – G. Grothendieck Jul 18 '22 at 13:24