R 中的多约束优化
Optimization with Multiple Constraints in R
我有一个关于使用几个约束优化建筑物中多个房间的程序使用的问题。 我的问题是如何同时根据数据和约束要求所有 4 个教室的最佳方案?
以下是我的一小部分数据。
Program sf 101 201 301 401
(1) Offices 120 6 6 5 5
(2) Gallery 1000 5 5 4 4
(3) Reception / Greeter 300 6 6 5 7
(4) Studio / Classroom 800 6 6 5 5
101、201、301 和 401 代表建筑物中的 4 个房间。
程序是潜在的房间用途。
sf 表示预期程序的最大平方英尺(一个约束)。
数据表示预期程序与每个房间的属性匹配的标准(这是我想要最大化的数字)。
我还想设置一些限制条件,允许我说我只想要建筑物中一定数量的办公室、画廊等。
例如,我想要 1 个 Reception/Greeter 和 2 个办公室,最后一个房间可以由最匹配的房间填充。 101 房间的最大面积为 150 平方英尺,201 房间的最大面积为 250 平方英尺,301 房间的最大面积为 1500 平方英尺,而 401 房间的最大面积为 500 平方英尺(这些限制不在我的数据框中,因为我不能想不出一个好的方法来包括它们)。
此示例应 return 101 = Offices,201 = Offices,301 = 除 Gallery 之外的三个之一,以及 401 = Reception / Greeter。
更新:
Objective 应该是这样的(我希望它们都最大化):
obj <- data1, data1, data1, data1 (and probably data$sf too)
那么我不太确定如何编写约束,但它们应该是这样的:
数据$101
数据$sf <= 150
此列中的解决方案数量应为 1
数据$201
数据$sf <= 250
此列中的解决方案数量应为 1
...
数据$401
数据 $sf <= 500
此列中的解决方案数量应为 1
然后最终以某种方式限制了 "Offices"、"Gallery"、"Reception / Greeter"、"Studio / Classroom" 的数量。
可能是这样的:
as.numeric(data$Program %in% c("(1) Offices") == 1
希望这能澄清一些事情。
听起来您正在将程序(data
中的行)分配给房间(data
中的列),以便最大化分配的价值。如果房间足够大,您只能将一个程序分配给一个房间,并且您只能将一个程序分配给一个房间,尽管同一个程序可以分配给多个房间(例如,您可以将 "Office" 分配给两个房间 101和 201)。因此,您的数据实际上由程序大小、房间大小和 objective 值组成:
program.size <- c(120, 1000, 300, 800)
room.size <- c(150, 250, 1500, 500)
(obj.vals <- matrix(c(6, 5, 6, 6, 6, 5, 6, 6, 5, 4, 5, 5, 5, 4, 7, 5), nrow=4))
# [,1] [,2] [,3] [,4]
# [1,] 6 6 5 5
# [2,] 5 5 4 4
# [3,] 6 6 5 7
# [4,] 6 6 5 5
阻止将程序分配给太小的房间的一种简单方法是将此类分配的 objective 值设置为较低的值(我将在此处使用 0):
(obj.adj <- obj.vals * outer(program.size, room.size, "<="))
# [,1] [,2] [,3] [,4]
# [1,] 6 6 5 5
# [2,] 0 0 4 0
# [3,] 0 0 5 7
# [4,] 0 0 5 0
现在,您可以使用整数规划来解决这个问题,定义一个变量 x_pr 如果程序 p 分配给房间 r 则取值为 1,否则为 0。您可以使用 R:
中的 lpSolve
包轻松编写 objective 和约束
# Convenience variables
nr <- nrow(obj.adj)
nc <- ncol(obj.adj)
# Model
library(lpSolve)
mod <- lp("max",
as.vector(obj.adj),
t(1*sapply(1:nc, function(x) rep(1:nc == x, each=nr))),
rep("<=", nc),
rep(1, nc),
all.bin=TRUE)
matrix(mod$solution, nrow=nr)
# [,1] [,2] [,3] [,4]
# [1,] 1 1 0 0
# [2,] 0 0 0 0
# [3,] 0 0 0 1
# [4,] 0 0 1 0
现在我们已经将 "Office" 分配给 101 和 201 房间,"Studio/Classroom" 分配给 301 房间,"Reception/Greeter" 分配给 401 房间。
值得注意的是,这个程序很容易通过为obj.adj
中的每个房间选择具有最大值的程序来解决,所以只有在你有更复杂的情况下才需要使用lpSolve
比问题中提到的限制更多。
我有一个关于使用几个约束优化建筑物中多个房间的程序使用的问题。 我的问题是如何同时根据数据和约束要求所有 4 个教室的最佳方案?
以下是我的一小部分数据。
Program sf 101 201 301 401
(1) Offices 120 6 6 5 5
(2) Gallery 1000 5 5 4 4
(3) Reception / Greeter 300 6 6 5 7
(4) Studio / Classroom 800 6 6 5 5
101、201、301 和 401 代表建筑物中的 4 个房间。
程序是潜在的房间用途。
sf 表示预期程序的最大平方英尺(一个约束)。
数据表示预期程序与每个房间的属性匹配的标准(这是我想要最大化的数字)。
我还想设置一些限制条件,允许我说我只想要建筑物中一定数量的办公室、画廊等。
例如,我想要 1 个 Reception/Greeter 和 2 个办公室,最后一个房间可以由最匹配的房间填充。 101 房间的最大面积为 150 平方英尺,201 房间的最大面积为 250 平方英尺,301 房间的最大面积为 1500 平方英尺,而 401 房间的最大面积为 500 平方英尺(这些限制不在我的数据框中,因为我不能想不出一个好的方法来包括它们)。
此示例应 return 101 = Offices,201 = Offices,301 = 除 Gallery 之外的三个之一,以及 401 = Reception / Greeter。
更新: Objective 应该是这样的(我希望它们都最大化):
obj <- data1, data1, data1, data1 (and probably data$sf too)
那么我不太确定如何编写约束,但它们应该是这样的:
数据$101
数据$sf <= 150
此列中的解决方案数量应为 1
数据$201
数据$sf <= 250
此列中的解决方案数量应为 1
...
数据$401
数据 $sf <= 500
此列中的解决方案数量应为 1
然后最终以某种方式限制了 "Offices"、"Gallery"、"Reception / Greeter"、"Studio / Classroom" 的数量。
可能是这样的:
as.numeric(data$Program %in% c("(1) Offices") == 1
希望这能澄清一些事情。
听起来您正在将程序(data
中的行)分配给房间(data
中的列),以便最大化分配的价值。如果房间足够大,您只能将一个程序分配给一个房间,并且您只能将一个程序分配给一个房间,尽管同一个程序可以分配给多个房间(例如,您可以将 "Office" 分配给两个房间 101和 201)。因此,您的数据实际上由程序大小、房间大小和 objective 值组成:
program.size <- c(120, 1000, 300, 800)
room.size <- c(150, 250, 1500, 500)
(obj.vals <- matrix(c(6, 5, 6, 6, 6, 5, 6, 6, 5, 4, 5, 5, 5, 4, 7, 5), nrow=4))
# [,1] [,2] [,3] [,4]
# [1,] 6 6 5 5
# [2,] 5 5 4 4
# [3,] 6 6 5 7
# [4,] 6 6 5 5
阻止将程序分配给太小的房间的一种简单方法是将此类分配的 objective 值设置为较低的值(我将在此处使用 0):
(obj.adj <- obj.vals * outer(program.size, room.size, "<="))
# [,1] [,2] [,3] [,4]
# [1,] 6 6 5 5
# [2,] 0 0 4 0
# [3,] 0 0 5 7
# [4,] 0 0 5 0
现在,您可以使用整数规划来解决这个问题,定义一个变量 x_pr 如果程序 p 分配给房间 r 则取值为 1,否则为 0。您可以使用 R:
中的lpSolve
包轻松编写 objective 和约束
# Convenience variables
nr <- nrow(obj.adj)
nc <- ncol(obj.adj)
# Model
library(lpSolve)
mod <- lp("max",
as.vector(obj.adj),
t(1*sapply(1:nc, function(x) rep(1:nc == x, each=nr))),
rep("<=", nc),
rep(1, nc),
all.bin=TRUE)
matrix(mod$solution, nrow=nr)
# [,1] [,2] [,3] [,4]
# [1,] 1 1 0 0
# [2,] 0 0 0 0
# [3,] 0 0 0 1
# [4,] 0 0 1 0
现在我们已经将 "Office" 分配给 101 和 201 房间,"Studio/Classroom" 分配给 301 房间,"Reception/Greeter" 分配给 401 房间。
值得注意的是,这个程序很容易通过为obj.adj
中的每个房间选择具有最大值的程序来解决,所以只有在你有更复杂的情况下才需要使用lpSolve
比问题中提到的限制更多。