R中的遗传算法(或优化)

时间:2013-11-23 21:35:55

标签: r optimization genetic-algorithm

我正在尝试使用R中的GA来探索优化领域。我意识到R可能不是我做这个的最佳位置,但这就是我现在所知道的。

所以这就是问题所在:我有一组人可以选择最有效地建造我的房子。我愿意花费最多10万美元来完成这项工作(解决方案不再有效的限制),我必须挑选一名电工,两名水管工,两名普通建筑工人,以及两名500名清单人所以(这个工作共有7个人)。

这些人中的每一个人都有他们将为工作收取的费率以及他们将为当前工作提供的总体价值(总和价值需要最大化)。请参阅此处的数据:

Data

我已经看过R包genalg和DeOptim,你可以使用二元函数来选择最大化给定价格的整体价值的人但是我不知道如何限制选择什么类型的工人。解决方案可以是所有电工,虽然它们都提供了很大的价值,但他们无法完成这项工作。所以基本上我正在寻找一种控制人口的方法,这些包似乎都不允许这样做。

有没有关于如何解决这个问题的想法?我相信你们中的许多人已经看过这个问题的变化并且有很好的洞察力。非常感谢您的帮助。

以下是我从论坛获得的代码:

library(genalg)

iter = 10
population = 500

# import csv file
brank = read.csv("GA_Data.csv")


dataset <- data.frame(item = brank$Person.ID, survivalpoints = brank$Value, weight = brank$Labor.Cost)


weightlimit <- 100000


monitor <- function(obj) {
  minEval = min(obj$evaluations);
  plot(obj$mean, obj$best, type="p", main = obj$iter); 
}

evalFunc <- function(x) {
  current_solution_survivalpoints <- x %*% dataset$survivalpoints
  current_solution_weight <- x %*% dataset$weight

  if (current_solution_weight > weightlimit) 
    return(0) else return(-current_solution_survivalpoints)
}


GAmodel <- rbga.bin(size = length(brank$Person.ID), popSize = population, iters = iter, mutationChance = 0.01, 
                    monitorFunc = monitor, elitism = T, zeroToOneRatio = 200, evalFunc = evalFunc)

cat(summary.rbga(GAmodel))

########################
# STOP and replace "space" with "comma" in a text file

solution = c(0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0)
# dataset[solution == 1, ]
brank[solution == 1, ]

sum(brank$Value[solution == 1])
sum(brank$Labor.Cost[solution == 1])

1 个答案:

答案 0 :(得分:5)

您的问题是线性编程(LP)任务,应该这样解决。 R有几个用于线性编程的包,这里我将使用lpSolve

我将您的数据放入数据框D(299名工作人员)。

str(D)
# 'data.frame': 299 obs. of  4 variables:
#  $ ID   : int  1 2 3 4 5 6 7 8 9 10 ...
#  $ Type : Factor w/ 4 levels "Cleanup Guy",..: 4 4 4 4 4 4 4 4 4 4 ...
#  $ Cost : int  5100 3900 5000 4500 6700 5000 4000 3500 7500 4500 ...
#  $ Value: int  25 18 23 20 29 21 17 15 32 19 ...

# Prepare constraint matrix
A <- matrix(0, nrow = 5, ncol = 299)
A[1, c(1:27, 279:299)] <- 1     # Plumbers
A[2, 28:97] <- 1                # Electricians
A[3, 98:190] <- 1               # Const Workers
A[4, 191:278] <- 1              # Cleanup
A[5, ] <- D$Cost                # cost <= 100000

# Prepare input for LP solver
objective.in <- D$Value
const.mat <- A
const.dir <- c(">=", ">=", ">=", ">=", "<=")
const.rhs <- c(1, 2, 2, 2, 100000)

# Now solve the problem
require(lpSolve)
sol <- lp(direction = "max", objective.in, # maximize objective function
        const.mat, const.dir, const.rhs,   # constraints
        all.bin = TRUE)                    # use binary variables only

# View the solution
sol
## Success: the objective function is 589
sum(D$Cost[inds])
## 100000
inds <- which(sol$solution == 1)
D[inds, ]
##      ID         Type Cost Value
## 1     1      Plumber 5100    25
## 51   51  Electrician 5000    24
## 54   54  Electrician 3500    16
## 101 101 Const Worker 3500    18
## 102 102 Const Worker 4400    21
## 103 103 Const Worker 5800    27
## 147 147 Const Worker 5600    29
## 149 149 Const Worker 3700    17
## 196 196  Cleanup Guy 6200    30
## 197 197  Cleanup Guy 4200    20
## 256 256  Cleanup Guy 4000    27
## 263 263  Cleanup Guy 3800    22
## 264 264  Cleanup Guy 3800    33
## 266 266  Cleanup Guy 3700    23
## 267 267  Cleanup Guy 4200    30
## 273 273  Cleanup Guy 3600    35
## 274 274  Cleanup Guy 5900    28
## 275 275  Cleanup Guy 3700    28
## 282 282      Plumber 7000    37
## 287 287      Plumber 3800    30
## 297 297      Plumber 3600    37
## 298 298      Plumber 5900    32

有关输入的说明,请参阅lp()功能的帮助页面。