【问题标题】:Genetic Algorithms (or optimization) in RR中的遗传算法(或优化)
【发布时间】:2013-11-24 20:24:19
【问题描述】:

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

所以问题来了:我可以挑选一组人来最有效地建造我的房子。我愿意为这份工作花费最多 100,000 美元(超出该限制的解决方案不再有效),我必须从 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])

【问题讨论】:

  • 你能告诉我们你的尝试吗?也许你可以提供一些我们可以复制/粘贴的代码?
  • 这样做了。您可以更改迭代和填充。还必须用逗号替换空格并将其粘贴到解决方案中以查看结果。

标签: r optimization genetic-algorithm


【解决方案1】:

您的问题是线性规划 (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() 函数的帮助页面。

【讨论】:

  • 这正是我想要的。非常感谢你的帮助。我几乎用蛮力的方式使用了六个 for 循环,但你让我免于等待程序在这些小数据集上运行的痛苦。
  • 我要注意的一点是,由于我正在寻找正好 2 名电工、const 工人和清理人员,因此我在 const.dir 中将 ">=" 替换为 "="。命令 sum(D$Cost[inds]) 也应该在 inds 之后
猜你喜欢
  • 2015-02-18
  • 2013-07-02
  • 2021-03-03
  • 2011-05-24
  • 2011-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多