这是上一个问题I asked的后续内容,但增加了一层额外的复杂性,因此是一个新问题。
我有两个组(在下面的示例中为 39 和 380 )。我需要做的是,将 889 人分为 2至7个人组成的39个组,以及 2至6 人之间的380个组。
但是,对可以属于某些组的人群的总数有一个限制。在下面的示例中,每一行允许的最大值在X6列中。
使用下面的示例。如果在第2行的X2列中分配了6个人,在X4列中分配了120个人,那么总人数将为18(6 * 3)+240(120 * 2)= 258,这样就可以了低于324。
因此,我在每一行中所得到的是X1 * X2 + X3 * X4的值(使列X5)小于或等于X6,且X2的总和为39,X4的总和为380,总和为X5的值为889。理想情况下,任何解决方案都应尽可能随机(因此,如果重复,则可能会得到不同的解决方案),并且当值与889、39和380不同时,该解决方案将起作用。
谢谢!
DF <- data.frame(matrix(0, nrow = 7, ncol = 6))
DF[,1] <- c(2:7,"Sum")
DF[7,2] <- 39
DF[2:6,3] <- 2:6
DF[7,4] <- 380
DF[7,5] <- 889
DF[1:6,6] <- c(359, 324, 134, 31, 5, 2)
DF[1,3:4] <- NA
DF[7,3] <- NA
DF[7,6] <- NA
编辑
我的问题的措辞可能不是最清楚的。这是我当前正在使用的代码的示例,以及该代码不符合我上面设置的条件的示例
homeType=rep(c("a", "b"), times=c(39, 380))
H <- vector(mode="list", length(homeType))
for(i in seq(H)){
H[[i]]$type <- homeType[i]
H[[i]]$n <- 0
}
# Place people in houses up to max number of people
npeople <- 889
for(i in seq(npeople)){
placed_in_house <- FALSE
while(!placed_in_house){
house_num <- sample(length(H), 1)
if(H[[house_num]]$type == "a"){
if(H[[house_num]]$n < 7){
H[[house_num]]$n <- H[[house_num]]$n + 1
placed_in_house <- TRUE
}
}
if(H[[house_num]]$type == "b"){
if(H[[house_num]]$n < 6){
H[[house_num]]$n <- H[[house_num]]$n + 1
placed_in_house <- TRUE
}
}
}
}
# move people around to get up to min number of people
for(i in seq(H)){
while(H[[i]]$n < 2){
knock_on_door <- sample(length(H), 1)
if( H[[knock_on_door]]$n > 2){
H[[i]]$n <- H[[i]]$n + 1 # house i takes 1 person
H[[knock_on_door]]$n <- H[[knock_on_door]]$n - 1 # house knock_on_door loses 1 person
}
}
}
Ha <- H[which(lapply(H, function(x){x$type}) == "a")]
Hb <- H[which(lapply(H, function(x){x$type}) == "b")]
Ha_T <- data.frame(t(table(data.frame(matrix(unlist(Ha), nrow=length(Ha), byrow=T)))))
Hb_T <- data.frame(t(table(data.frame(matrix(unlist(Hb), nrow=length(Hb), byrow=T)))))
DF_1 <- data.frame(matrix(0, nrow = 7, ncol = 6))
DF_1[,1] <- c(2:7,"Sum")
DF_1[7,2] <- 39
DF_1[2:6,3] <- 2:6
DF_1[7,4] <- 380
DF_1[7,5] <- 889
DF_1[1:6,6] <- c(359, 324, 134, 31, 5, 2)
for(i in 1:nrow(Ha_T)){DF_1[as.numeric(as.character(Ha_T[i,1]))-1,2] <- Ha_T[i,3]}
for(i in 1:nrow(Hb_T)){DF_1[as.numeric(as.character(Hb_T[i,1])),4] <- Hb_T[i,3]}
DF_1$X5[1:6] <- (as.numeric(as.character(DF_1$X1[1:6]))*DF_1$X2[1:6])+(as.numeric(as.character(DF_1$X3[1:6]))*DF_1$X4[1:6])
DF_1$X7 <- DF_1$X2+DF_1$X4
DF_1[1,3:4] <- NA
DF_1[7,3] <- NA
DF_1[7,6] <- NA
使用此示例,问题出在DF_1中的第2行。 X7列(X2 + X4)中的值大于X6列中显示的允许数字。我需要的是一个解决方案,其中X7中的值小于或等于X6中的值,但是X2,X4和X5列的总和(X1 * X2 + X3 * X4)分别等于39、380和889(尽管这些数字会根据所使用的数据而变化)。
最佳答案
问题中对问题的原始描述无法满足,因为没有任何值可以满足所有这些约束。
但是,在注释中重述了该问题之后,可以按以下方式解决该问题的修订说明。
更新:基于澄清问题的解决方案
根据评论中的澄清
基于此更新的信息,我们可以执行以下操作:循环1)根据标准计算每种类型可以分配多少个房屋,2)随机选择一种仍可以分配而又不违反的房屋类型规则3)之一,重复直到所有889名 child 都在房子里。请注意,我在这里使用了更具描述性的列名,以使遵循逻辑更加容易:
DT <- data.table(HS1 = 2:7, # type 1 house size
NH1 = 0, # number of type 1 houses with children
HS2 = 1:6, # type 2 house size
NH2 = 0, # number of type 2 houses with children
C = 0, # number of children in houses
MaxNH = c(359, 324, 134, 31, 5, 2)) # maximum number of type1+type 2 houses
NR = DT[,.N]
set.seed(1234)
repeat {
while (DT[, sum(C) < 889]) {
DT[, MaxH1 := (MaxNH - NH1 - NH2)]
DT[, MaxH2 := (MaxNH - NH1 - NH2)]
DT[1,MaxH2 := 0 ]
DT[MaxH1 > 39 - sum(NH1), MaxH1 := 39 - sum(NH1)]
DT[MaxH2 > 380- sum(NH2), MaxH2 := 380- sum(NH2)]
if (DT[, sum(NH1)] >= 39) DT[, MaxH1 := 0]
if (DT[, sum(NH2)] >= 380) DT[, MaxH1 := 0]
if (DT[, all(MaxH1==0) & all(MaxH2==0)]) { # check if it is not possible to assign anyone else to a group
print("No solution found. Check constraints or try again")
break
}
# If you wish to preferentially fill a particular type of house, then change the probability weights in the next line accordingly
newgroup = sample(2*NR, 1, prob = DT[, c(MaxH1, MaxH2)])
if (newgroup > NR) DT[rep(1:NR, 2)[newgroup], NH2 := NH2+1] else DT[rep(1:NR, 2)[newgroup], NH1 := NH1+1]
DT[, C := HS1*NH1 + HS2*NH2]
}
if (DT[, sum(C)==889]) break
}
DT[,1:6, with=F]
# HS1 NH1 HS2 NH2 C MaxNH
#1: 2 7 1 0 14 359
#2: 3 7 2 218 457 324
#3: 4 14 3 76 284 134
#4: 5 9 4 14 101 31
#5: 6 2 5 3 27 5
#6: 7 0 6 1 6 2
colSums(DT[, .(NH1, NH2, C)])
# NH1 NH2 C
# 39 312 889