如何找到满足 R 中某些线性约束的向量值(仅整数)?
How to find the vector's values (only integers) which satisfies some linear constraints in R?
给定一个向量和一个总和,例如 limits = c(1,2,5,6,7,6) 和
总和 = 10。
给定的约束是:
x1 <= 限制[1]
x2 <= 限制[2]
x3 <= 限制[3]
x4 <= 限制[4]
x5 <= 限制[5]
x6 <= 限制[6]
x1+x2+x3+x4+x5+x6 = 总和
我想找到满足这些约束的单个向量:c(x1,x2,x3,x4,x5,x6)。我写了这个:
get_vector <-function(sum, limits){
res_vec <-c()
left <- sum
for (i in seq(1:(length(limits)-1))){
res_vec<-c(res_vec, sample(c(0:min(limits[i],left)), 1))
left <- left - res_vec[i]
}
res_vec[length(limits)] <- left
}
return (res_vec)
}
不过好像时不时会失效(我查过了)。
有人可以给出更准确的建议来解决这个问题吗?
谢谢
limits = c(1,2,5,6,7,6)
mysum = 10
set.seed(42)
ans = setNames(limits, paste0("x", 1:length(limits)))
while(sum(ans) > mysum){
ind = sample(which(ans > 1), 1)
ans[ind] = ans[ind] - 1
}
ans
#x1 x2 x3 x4 x5 x6
# 1 1 4 2 1 1
sum(ans)
#[1] 10
这是获得所有可能解决方案的方法。
library(partitions)
allPartitions <- compositions(10, 6, include.zero = FALSE)
limits <- c(1, 2, 5, 6, 7, 6)
good <- apply(allPartitions, 2, function(x) all(x <= limits))
results <- allPartitions[, good]
> t(results)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 4 1 1 1
[2,] 1 1 5 1 1 1
[3,] 1 2 3 2 1 1
[4,] 1 1 4 2 1 1
[5,] 1 2 2 3 1 1
[6,] 1 1 3 3 1 1
[7,] 1 2 1 4 1 1
[8,] 1 1 2 4 1 1
[9,] 1 1 1 5 1 1
[10,] 1 2 3 1 2 1
[11,] 1 1 4 1 2 1
[12,] 1 2 2 2 2 1
[13,] 1 1 3 2 2 1
[14,] 1 2 1 3 2 1
[15,] 1 1 2 3 2 1
[16,] 1 1 1 4 2 1
[17,] 1 2 2 1 3 1
[18,] 1 1 3 1 3 1
[19,] 1 2 1 2 3 1
[20,] 1 1 2 2 3 1
[21,] 1 1 1 3 3 1
[22,] 1 2 1 1 4 1
[23,] 1 1 2 1 4 1
[24,] 1 1 1 2 4 1
[25,] 1 1 1 1 5 1
[26,] 1 2 3 1 1 2
[27,] 1 1 4 1 1 2
[28,] 1 2 2 2 1 2
[29,] 1 1 3 2 1 2
[30,] 1 2 1 3 1 2
[31,] 1 1 2 3 1 2
[32,] 1 1 1 4 1 2
[33,] 1 2 2 1 2 2
[34,] 1 1 3 1 2 2
[35,] 1 2 1 2 2 2
[36,] 1 1 2 2 2 2
[37,] 1 1 1 3 2 2
[38,] 1 2 1 1 3 2
[39,] 1 1 2 1 3 2
[40,] 1 1 1 2 3 2
[41,] 1 1 1 1 4 2
[42,] 1 2 2 1 1 3
[43,] 1 1 3 1 1 3
[44,] 1 2 1 2 1 3
[45,] 1 1 2 2 1 3
[46,] 1 1 1 3 1 3
[47,] 1 2 1 1 2 3
[48,] 1 1 2 1 2 3
[49,] 1 1 1 2 2 3
[50,] 1 1 1 1 3 3
[51,] 1 2 1 1 1 4
[52,] 1 1 2 1 1 4
[53,] 1 1 1 2 1 4
[54,] 1 1 1 1 2 4
[55,] 1 1 1 1 1 5
或者,更简洁或许更高效:
> results <- sweep(blockparts(limits-1,10-6), 1, c(1,1,1,1,1,1), "+")
> t(results)
[1,] 1 2 4 1 1 1
[2,] 1 1 5 1 1 1
[3,] 1 2 3 2 1 1
[4,] 1 1 4 2 1 1
[5,] 1 2 2 3 1 1
[6,] 1 1 3 3 1 1
[7,] 1 2 1 4 1 1
[8,] 1 1 2 4 1 1
[9,] 1 1 1 5 1 1
[10,] 1 2 3 1 2 1
[11,] 1 1 4 1 2 1
[12,] 1 2 2 2 2 1
[13,] 1 1 3 2 2 1
[14,] 1 2 1 3 2 1
[15,] 1 1 2 3 2 1
[16,] 1 1 1 4 2 1
[17,] 1 2 2 1 3 1
[18,] 1 1 3 1 3 1
[19,] 1 2 1 2 3 1
[20,] 1 1 2 2 3 1
[21,] 1 1 1 3 3 1
[22,] 1 2 1 1 4 1
[23,] 1 1 2 1 4 1
[24,] 1 1 1 2 4 1
[25,] 1 1 1 1 5 1
[26,] 1 2 3 1 1 2
[27,] 1 1 4 1 1 2
[28,] 1 2 2 2 1 2
[29,] 1 1 3 2 1 2
[30,] 1 2 1 3 1 2
[31,] 1 1 2 3 1 2
[32,] 1 1 1 4 1 2
[33,] 1 2 2 1 2 2
[34,] 1 1 3 1 2 2
[35,] 1 2 1 2 2 2
[36,] 1 1 2 2 2 2
[37,] 1 1 1 3 2 2
[38,] 1 2 1 1 3 2
[39,] 1 1 2 1 3 2
[40,] 1 1 1 2 3 2
[41,] 1 1 1 1 4 2
[42,] 1 2 2 1 1 3
[43,] 1 1 3 1 1 3
[44,] 1 2 1 2 1 3
[45,] 1 1 2 2 1 3
[46,] 1 1 1 3 1 3
[47,] 1 2 1 1 2 3
[48,] 1 1 2 1 2 3
[49,] 1 1 1 2 2 3
[50,] 1 1 1 1 3 3
[51,] 1 2 1 1 1 4
[52,] 1 1 2 1 1 4
[53,] 1 1 1 2 1 4
[54,] 1 1 1 1 2 4
[55,] 1 1 1 1 1 5
给定一个向量和一个总和,例如 limits = c(1,2,5,6,7,6) 和 总和 = 10。 给定的约束是:
x1 <= 限制[1]
x2 <= 限制[2]
x3 <= 限制[3]
x4 <= 限制[4]
x5 <= 限制[5]
x6 <= 限制[6]
x1+x2+x3+x4+x5+x6 = 总和
我想找到满足这些约束的单个向量:c(x1,x2,x3,x4,x5,x6)。我写了这个:
get_vector <-function(sum, limits){
res_vec <-c()
left <- sum
for (i in seq(1:(length(limits)-1))){
res_vec<-c(res_vec, sample(c(0:min(limits[i],left)), 1))
left <- left - res_vec[i]
}
res_vec[length(limits)] <- left
}
return (res_vec)
}
不过好像时不时会失效(我查过了)。 有人可以给出更准确的建议来解决这个问题吗?
谢谢
limits = c(1,2,5,6,7,6)
mysum = 10
set.seed(42)
ans = setNames(limits, paste0("x", 1:length(limits)))
while(sum(ans) > mysum){
ind = sample(which(ans > 1), 1)
ans[ind] = ans[ind] - 1
}
ans
#x1 x2 x3 x4 x5 x6
# 1 1 4 2 1 1
sum(ans)
#[1] 10
这是获得所有可能解决方案的方法。
library(partitions)
allPartitions <- compositions(10, 6, include.zero = FALSE)
limits <- c(1, 2, 5, 6, 7, 6)
good <- apply(allPartitions, 2, function(x) all(x <= limits))
results <- allPartitions[, good]
> t(results)
[,1] [,2] [,3] [,4] [,5] [,6]
[1,] 1 2 4 1 1 1
[2,] 1 1 5 1 1 1
[3,] 1 2 3 2 1 1
[4,] 1 1 4 2 1 1
[5,] 1 2 2 3 1 1
[6,] 1 1 3 3 1 1
[7,] 1 2 1 4 1 1
[8,] 1 1 2 4 1 1
[9,] 1 1 1 5 1 1
[10,] 1 2 3 1 2 1
[11,] 1 1 4 1 2 1
[12,] 1 2 2 2 2 1
[13,] 1 1 3 2 2 1
[14,] 1 2 1 3 2 1
[15,] 1 1 2 3 2 1
[16,] 1 1 1 4 2 1
[17,] 1 2 2 1 3 1
[18,] 1 1 3 1 3 1
[19,] 1 2 1 2 3 1
[20,] 1 1 2 2 3 1
[21,] 1 1 1 3 3 1
[22,] 1 2 1 1 4 1
[23,] 1 1 2 1 4 1
[24,] 1 1 1 2 4 1
[25,] 1 1 1 1 5 1
[26,] 1 2 3 1 1 2
[27,] 1 1 4 1 1 2
[28,] 1 2 2 2 1 2
[29,] 1 1 3 2 1 2
[30,] 1 2 1 3 1 2
[31,] 1 1 2 3 1 2
[32,] 1 1 1 4 1 2
[33,] 1 2 2 1 2 2
[34,] 1 1 3 1 2 2
[35,] 1 2 1 2 2 2
[36,] 1 1 2 2 2 2
[37,] 1 1 1 3 2 2
[38,] 1 2 1 1 3 2
[39,] 1 1 2 1 3 2
[40,] 1 1 1 2 3 2
[41,] 1 1 1 1 4 2
[42,] 1 2 2 1 1 3
[43,] 1 1 3 1 1 3
[44,] 1 2 1 2 1 3
[45,] 1 1 2 2 1 3
[46,] 1 1 1 3 1 3
[47,] 1 2 1 1 2 3
[48,] 1 1 2 1 2 3
[49,] 1 1 1 2 2 3
[50,] 1 1 1 1 3 3
[51,] 1 2 1 1 1 4
[52,] 1 1 2 1 1 4
[53,] 1 1 1 2 1 4
[54,] 1 1 1 1 2 4
[55,] 1 1 1 1 1 5
或者,更简洁或许更高效:
> results <- sweep(blockparts(limits-1,10-6), 1, c(1,1,1,1,1,1), "+")
> t(results)
[1,] 1 2 4 1 1 1
[2,] 1 1 5 1 1 1
[3,] 1 2 3 2 1 1
[4,] 1 1 4 2 1 1
[5,] 1 2 2 3 1 1
[6,] 1 1 3 3 1 1
[7,] 1 2 1 4 1 1
[8,] 1 1 2 4 1 1
[9,] 1 1 1 5 1 1
[10,] 1 2 3 1 2 1
[11,] 1 1 4 1 2 1
[12,] 1 2 2 2 2 1
[13,] 1 1 3 2 2 1
[14,] 1 2 1 3 2 1
[15,] 1 1 2 3 2 1
[16,] 1 1 1 4 2 1
[17,] 1 2 2 1 3 1
[18,] 1 1 3 1 3 1
[19,] 1 2 1 2 3 1
[20,] 1 1 2 2 3 1
[21,] 1 1 1 3 3 1
[22,] 1 2 1 1 4 1
[23,] 1 1 2 1 4 1
[24,] 1 1 1 2 4 1
[25,] 1 1 1 1 5 1
[26,] 1 2 3 1 1 2
[27,] 1 1 4 1 1 2
[28,] 1 2 2 2 1 2
[29,] 1 1 3 2 1 2
[30,] 1 2 1 3 1 2
[31,] 1 1 2 3 1 2
[32,] 1 1 1 4 1 2
[33,] 1 2 2 1 2 2
[34,] 1 1 3 1 2 2
[35,] 1 2 1 2 2 2
[36,] 1 1 2 2 2 2
[37,] 1 1 1 3 2 2
[38,] 1 2 1 1 3 2
[39,] 1 1 2 1 3 2
[40,] 1 1 1 2 3 2
[41,] 1 1 1 1 4 2
[42,] 1 2 2 1 1 3
[43,] 1 1 3 1 1 3
[44,] 1 2 1 2 1 3
[45,] 1 1 2 2 1 3
[46,] 1 1 1 3 1 3
[47,] 1 2 1 1 2 3
[48,] 1 1 2 1 2 3
[49,] 1 1 1 2 2 3
[50,] 1 1 1 1 3 3
[51,] 1 2 1 1 1 4
[52,] 1 1 2 1 1 4
[53,] 1 1 1 2 1 4
[54,] 1 1 1 1 2 4
[55,] 1 1 1 1 1 5