6

Я довольно новичок в R, и я пытаюсь написать сценарий для того, что я использовал с Solver в Excel. В моих данных ниже, у меня есть список работников с типами работ A-E. У каждого работника есть заработная плата и производственная ставка. То, что я хочу сделать R, - это найти максимальную добычу, которую я могу получить от 10 работников с суммарной зарплатой < 100 000. Ограничения состоят в том, что мне требуется в общей сложности 10 работников, и мне нужно 2 из типов работ A-D, 1 из E и 1 любого типа.Как использовать R для решения/выбора лучших людей для работы - с ограничениями?

Я искал и искал способ сделать это с оптимизацией, IpSolve и т. Д., Но с моими ограниченными знаниями мне не повезло.

Благодарим за помощь!

Name Pos Salary Producton 
Joe  A 12001 13.1 
Jim  A 17753 23.5 
Jill A 11447 14.8 
Brian A 11447 14.8 
Sally B 2171 1.2 
Nancy B 4537 2.1 
Francis B 2840 1.8 
Ace  B 2840 1.8 
Bill C 3818 1.6 
Ted  C 11447 0.1 
Henry C 2000 1.1 
Kyle C 3818 1.6 
Sam  D 11447 0.1 
Trevor D 2000 1.1 
John D 4317 11.7 
Jerome D 2000 1.1 
Rebecca E 3818 1.6 
Sunny E 11447 0.1 
Britt E 2000 1.1 
Sara E 4317 11.7 
+0

Да, как минимум 2. Спасибо! –

+0

Просто подумайте: выберите (20,10) = 184756, поэтому не потребуется столько времени, чтобы протестировать каждую возможную комбинацию в этом маленьком корпусе. Если, конечно, это домашнее задание, и вы * должны * использовать решатель. –

+0

К счастью, это не домашнее задание, но полный список насчитывает более трехсот человек. Моя ошибка, я должен был упомянуть об этом в оригинальном посте. –

ответ

6

Использование lp в пакете lpSolve решить основную проблему целочисленного программирования. Первые 5 ограничений относятся к числу позиций A, B, C, D и E соответственно, 6-е число зависит от количества сотрудников, а 7-е - от общей заработной платы. Предполагая, что DF является кадр данных показано на вопрос, попробуйте следующее:

library(lpSolve) 

obj <- DF$Prod 
con <- rbind(t(model.matrix(~ Pos + 0, DF)), rep(1, nrow(DF)), DF$Salary) 
dir <- c(">=", ">=", ">=", ">=", ">=", "==", "<") 
rhs <- c(2, 2, 2, 2, 1, 10, 100000) 

result <- lp("max", obj, con, dir, rhs, all.bin = TRUE) 

, который дает:

> result 
Success: the objective function is 84.7 
> DF[result$solution == 1, ] 
    Name Pos Salary Producton 
2  Jim A 17753  23.5 
3 Jill A 11447  14.8 
4 Brian A 11447  14.8 
6 Nancy B 4537  2.1 
8  Ace B 2840  1.8 
9 Bill C 3818  1.6 
12 Kyle C 3818  1.6 
14 Trevor D 2000  1.1 
15 John D 4317  11.7 
20 Sara E 4317  11.7 

Обратите внимание, что Производство опечатка в вопросе или, возможно, что было задумано.

ДОБАВЛЕНО:

Что касается второго наилучшего решения Идея заключается в том, чтобы добавить ограничение, которое делает лучшее решение неосуществимо, но не исключает другие возможные решения:

con2 <- rbind(con, result$solution) 
dir2 <- c(dir, "<=") 
rhs2 <- c(rhs, 9) 
result2 <- lp("max", obj, con2, dir2, rhs2, all.bin = TRUE) 

В этом случае мы получаем следующее которая имеет ту же самую оптимальную объективную ценность, как лучшее решение, поэтому было бы так же хорошо:

> result2 
Success: the objective function is 84.7 
> DF[result2$solution == 1, ] 
    Name Pos Salary Producton 
2  Jim A 17753  23.5 
3 Jill A 11447  14.8 
4 Brian A 11447  14.8 
6 Nancy B 4537  2.1 
8  Ace B 2840  1.8 
9 Bill C 3818  1.6 
12 Kyle C 3818  1.6 
15 John D 4317  11.7 
16 Jerome D 2000  1.1 
20 Sara E 4317  11.7 

есть также аргументы lp, которые позволяют создавать сразу несколько решений; однако в файле справки упоминаются некоторые ошибки, и может быть безопаснее использовать вышеуказанный подход.

+0

Удивительно, большое вам спасибо! Как обледенение на торте, есть ли способ получить 2-е лучшее решение? –

+0

Вопрос: Я думал о таком алгоритме, как: 1) рассчитать показатель заслуг, т. Е. Производство/зарплату, 2) захватить главного кандидата FOM из каждой требуемой категории (AE), 3) заполнить оставшиеся слоты верхней оставшейся FOM значения. Это то, что делает 'lpSolve'? –

+0

@Derek, добавили второе лучшее решение. @Carl, 'lp' использует алгоритм ветвления и привязки. –