gpt4 book ai didi

r - 在 R 中使用字符和列总和约束的 lpSolve

转载 作者:行者123 更新时间:2023-12-03 16:00:13 24 4
gpt4 key购买 nike

我有一个房间列表、房间的最大平方英尺、程序、程序的最大平方英尺以及房间与预期程序使用匹配(匹配 #)的程度的值。在帮助下,我已经能够最大限度地利用每个房间一个程序的匹配数量和平方英尺。但是,我想更进一步地进行这种分析,并允许在同一个房间内有多个程序或同一程序的倍数,如果它具有最高的匹配#,只要倍数仍然符合平方英尺的要求。此外,我想告诉 lpSolve,我只想要“x”个办公室,“y”个工作室,等等。到目前为止,这是我的数据和代码:

program.size <- c(120,320,300,800,500,1000,500,1000,1500,400,1500,2000)
room.size <- c(1414,682,1484,2938,1985,1493,427,1958,708,581,1485,652,727,2556,1634,187,2174,205,1070,2165,1680,1449,1441,2289,986,298,590,2925)
(obj.vals <- matrix(c(3,4,2,8,3,7,4,8,6,4,7,7,
3,4,2,8,3,7,4,8,6,4,7,7,
4,5,3,7,4,6,5,7,5,3,6,6,
2,3,1,7,2,6,3,7,7,5,6,6,
4,5,3,7,4,6,5,7,5,3,6,6,
3,6,4,8,5,7,4,8,7,7,7,7,
3,4,2,8,3,7,4,8,6,4,7,7,
4,5,3,7,4,6,5,7,5,3,6,6,
6,7,5,7,6,6,7,7,5,3,6,6,
6,7,5,7,6,6,7,7,5,3,6,6,
5,6,6,6,5,7,8,6,4,2,5,5,
6,7,5,7,6,6,7,7,5,3,6,6,
6,7,5,7,6,6,7,7,5,3,6,6,
3,4,4,8,3,9,6,8,6,4,7,7,
3,4,2,6,3,5,4,6,6,4,5,5,
4,5,3,5,4,4,5,5,5,3,4,4,
5,6,4,8,5,7,6,8,6,4,7,7,
5,6,4,8,5,7,6,8,6,4,7,7,
4,5,5,7,4,8,7,7,5,3,6,6,
5,6,4,8,5,7,6,8,6,4,7,7,
3,4,2,6,3,5,4,6,6,4,5,5,
5,6,4,8,5,7,6,8,6,4,7,7,
5,6,4,8,5,7,6,8,6,4,7,7,
5,4,4,6,5,5,6,6,6,6,7,5,
6,5,5,5,6,4,5,5,5,7,6,4,
4,5,3,7,4,6,5,7,7,5,6,6,
6,5,5,5,6,4,5,5,5,7,6,4,
3,4,4,6,3,7,6,6,6,4,5,5), nrow=12))
rownames(obj.vals) <- c("Enclosed Offices", "Open Office", "Reception / Greeter", "Studio / Classroom",
"Conference / Meeting Room", "Gallery", "Public / Lobby / Waiting",
"Collaborative Space", "Mechanical / Support", "Storage / Archives",
"Fabrication", "Performance")
(obj.adj <- obj.vals * outer(program.size, room.size, "<="))


nr <- nrow(obj.adj)
nc <- ncol(obj.adj)

library(lpSolve)
obj <- as.vector(obj.adj)
con <- t(1*sapply(1:nc, function(x) rep(1:nc == x, each=nr)))
dir <- rep("<=", nc)
rhs <- rep(1, nc)
mod <- lp("max", obj, con, dir, rhs, all.bin=TRUE)

final <- matrix(mod$solution, nrow=nr)

所以现在我的问题是如何让求解器最大限度地使用平方英尺并匹配每个房间(列)内的 # 并允许多个相同的程序或多个程序的组合来实现这一点?我知道我必须取消“mod”中的“<= 1”限制,但我不知道如何让它在每个房间中找到最适合的,然后最终找到整体。

房间 [,1] 的解决方案是:
$optimum
33

它将尝试在房间内安装 11 个封闭式办公室,这些办公室的最佳匹配值比 1 个协作空间(8 个匹配项)和 1 个存储/文件库(4 个匹配项)高得多,总共 12 个匹配项。

因此,这引出了我的下一个问题,即限制解决方案矩阵中某些程序的总数。我认为它会包括某种
as.numeric(data$EnclosedOffices "<=" 5)

但我也无法弄清楚如何限制它。所有程序的这些数字都不同。

感谢您的任何帮助,并随时要求任何澄清。

更新:
约束
  • 最大化每个房间的匹配 # (obj.vals)。
  • 最大化每个房间内的程序大小平方英尺
    脚。通过多次使用同一个程序 (5 x
    封闭式办公室)或组合程序(1 个协作空间和
    1 性能)。
  • 限制和/或强制返回的程序数量
    解决方案。只要不超过我在所有房间中为该程序提供的最大数量,程序就可以在房间之间拆分。 (在所有 28 列中只能选择 5 个封闭式办公室、8 个工作室/教室、1 个制造等。
  • 最佳答案

    如果您使用 R 包 lpSolveAPI (lpSolve 的包装器)然后它变得更容易一些。
    首先,看看数学公式(整数程序),然后我向您展示解决您问题的代码。
    公式
    X_r_p是采用正整数值的决策变量。X_r_p = 类型程序的数量 p分配到房间r(在您的所有问题中将有 28*12=336 个决策变量)
    目标函数
    最大化匹配分数Max sum(r) sum(p) C_r_p * X_r_p # 这里C_r_p是将p分配给房间r的分数
    受制于
    房间面积限制约束

    Sum(p) Max_area_p * X_r_p <= Room Size (r) for each room r
    (我们将有 28 个这样的约束)
    限制程序数量约束
    Sum(r) X_r_p <= Max_allowable(p) for each program p
    (我们将有 12 个这样的约束)
     X_r_p >= 0, Integer
    这就是所有的公式。 336 列和 40 行。
    在 R 中实现
    这是 R 中的一个实现,使用 lpSolveAPI .
    注意:由于 OP 没有在建筑物中提供 max_allowable 程序,我为 max_programs. 生成了自己的数据。
    program.size <- c(120,320,300,800,500,1000,500,1000,1500,400,1500,2000)
    room.size <- c(1414,682,1484,2938,1985,1493,427,1958,708,581,1485,652,727,2556,1634,187,2174,205,1070,2165,1680,1449,1441,2289,986,298,590,2925)
    (obj.vals <- matrix(c(3,4,2,8,3,7,4,8,6,4,7,7,3,4,2,8,3,7,4,8,6,4,7,7,
    4,5,3,7,4,6,5,7,5,3,6,6,2,3,1,7,2,6,3,7,7,5,6,6, 4,5,3,7,4,6,5,7,5,3,6,6,
    3,6,4,8,5,7,4,8,7,7,7,7,3,4,2,8,3,7,4,8,6,4,7,7, 4,5,3,7,4,6,5,7,5,3,6,6,
    6,7,5,7,6,6,7,7,5,3,6,6,6,7,5,7,6,6,7,7,5,3,6,6, 5,6,6,6,5,7,8,6,4,2,5,5,
    6,7,5,7,6,6,7,7,5,3,6,6, 6,7,5,7,6,6,7,7,5,3,6,6, 3,4,4,8,3,9,6,8,6,4,7,7,
    3,4,2,6,3,5,4,6,6,4,5,5, 4,5,3,5,4,4,5,5,5,3,4,4, 5,6,4,8,5,7,6,8,6,4,7,7,
    5,6,4,8,5,7,6,8,6,4,7,7, 4,5,5,7,4,8,7,7,5,3,6,6, 5,6,4,8,5,7,6,8,6,4,7,7,
    3,4,2,6,3,5,4,6,6,4,5,5, 5,6,4,8,5,7,6,8,6,4,7,7, 5,6,4,8,5,7,6,8,6,4,7,7,
    5,4,4,6,5,5,6,6,6,6,7,5, 6,5,5,5,6,4,5,5,5,7,6,4, 4,5,3,7,4,6,5,7,7,5,6,6,
    6,5,5,5,6,4,5,5,5,7,6,4, 3,4,4,6,3,7,6,6,6,4,5,5), nrow=12))
    rownames(obj.vals) <- c("Enclosed Offices", "Open Office", "Reception / Greeter", "Studio / Classroom",
    "Conference / Meeting Room", "Gallery", "Public / Lobby / Waiting",
    "Collaborative Space", "Mechanical / Support", "Storage / Archives",
    "Fabrication", "Performance")
    对于 12 个程序中的每一个,让我们设置可以分配给所有房间组合的最大重复次数。请注意,这是我添加的内容,因为该数据不是由 OP 提供的。 (限制他们被分配到太多房间。)
    max_programs <- c(1,2,3,1,5,2,3,4,1,3,1,2)

    library(lpSolveAPI)

    nrooms <- 28
    nprgs <- 12
    ncol = nrooms*nprgs

    lp_matching <- make.lp(ncol=ncol)
    #we want integer assignments
    set.type(lp_matching, columns=1:ncol, type = c("integer"))

    # sum r,p Crp * Xrp
    set.objfn(lp_matching, obj.vals) #28 rooms * 12 programs
    lp.control(lp_matching,sense='max')

    #' Set Max Programs constraints
    #' No more than max number of programs over all the rooms
    #' X1p + x2p + x3p ... + x28p <= max(p) for each p
    Add_Max_program_constraint <- function (prog_index) {
    prog_cols <- (0:(nrooms-1))*nprgs + prog_index
    add.constraint(lp_matching, rep(1,nrooms), indices=prog_cols, rhs=max_programs[prog_index])
    }
    #Add a max_number constraint for each program
    lapply(1:nprgs, Add_Max_program_constraint)

    #' Sum of all the programs assigned to each room, over all programs
    #' area_1 * Xr1+ area 2* Xr2+ ... + area12* Xr12 <= room.size[r] for each room
    Add_room_size_constraint <- function (room_index) {
    room_cols <- (room_index-1)*nprgs + (1:nprgs) #relevant columns for a given room
    add.constraint(lp_matching, xt=program.size, indices=room_cols, rhs=room.size[room_index])
    }
    #Add a max_number constraint for each program
    lapply(1:nrooms, Add_room_size_constraint)
    要解决这个问题:
    > solve(lp_matching)
    > get.objective(lp_matching)
    [1] 195
    get.variables(lp_matching) # to see which programs went to which rooms

    > print(lp_matching)
    Model name:
    a linear program with 336 decision variables and 40 constraints
    您还可以将 IP 模型写入文件以进行检查:
    #Give identifiable column and row names
    rp<- t(outer(1:nrooms, 1:nprgs, paste, sep="_"))
    rp_vec <- paste(abc, sep="")
    colnames<- paste("x_",rp_vec, sep="")
    # RowNames
    rownames1 <- paste("MaxProg", 1:nprgs, sep="_")
    rownames2 <- paste("Room", 1:nrooms, "AreaLimit", sep="_")
    dimnames(lp_matching) <- list(c(rownames1, rownames2), colnames)

    write.lp(lp_matching,filename="room_matching.lp")
    希望有帮助。
    根据后续问题更新
    跟进问题 1:更改代码以确保每个房间至少有一个程序。
    添加以下约束集:
    X_r_p >= 1 for all r
    注意:由于这是一个最大化问题,默认情况下最佳解决方案应遵守此约束。换句话说,如果可以的话,它总是将程序分配到任何房间,假设分配的分数为正。
    跟进问题2:另一个问题是,我是否可以要求它总共有28个以上的程序?例如,如果我想要 28 个封闭式办公室,它们几乎都可以放在一个 2938 平方英尺的房间里。如果最大值设置为 28,我怎么能要求 R 仍然找到其他程序?
    为了实现这个目标,你可以做一些不同的事情。根本没有所有程序的总和 <= 28 约束。 (如果您在上面的解决方案中注意到,我的约束略有不同。)
    约束:
     Sum(r) X_r_p <= Max_allowable(p) for each program p
    仅限制每种程序类型的最大值。总数没有限制。此外,您不必为每种类型的程序编写一个这样的约束。仅当您想限制其出现时才编写此约束。
    为了概括这一点,您可以设置每种类型程序总数的下限和上限。这将使您对分配进行非常精细的控制。
    min_allowable(p) <= sum(over r) X_r_p <= max_allowable(p) for any program type p

    关于r - 在 R 中使用字符和列总和约束的 lpSolve,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31813686/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com