这是原始表:
Column1 Column2
Row1 4 (x1) 6(x3)
Row2 5 (x2) 4(x4)
x1
,x2
,x3
,x4
表示交换后的新值
最初,每列的差异为:
Var(column1)= var(c(4,5))=0.5
Var(column2)= var(c(6,4))=2
交换原始表中小于10的值后,两列的新方差分别为:
New_Var(column1)=(x1-(x1+x2)/2)^2+(x2-(x1+x2)/2)^2
New_Var(column2)=(x3-(x3+x4)/2)^2+(x4-(x3+x4)/2)^2
我的目标是
Minimize | New_Var(column1) – 0.5 | + | New_Var(column2) – 2 |
此处表示法‘| |’表示绝对。
约束是x1
,x2
,x3
,x4
只能分别从固定域(这里说{4, 5, 4, 6}
)获取值。并且所有四个变量都需要交换为不同的值,例如x1
不能为4,x3
不能为6,依此类推。
请注意,此处原始表中的所有值都大于10,因为我只是想使问题看起来简单。
实际上,该表是6000*10
,非常大。因此,输出所有唯一的排列和测试是不合适的方法。
我已经阅读了R中的task view of optimization
。那里有很多优化包。所以我需要更具体的指导。
以下是可以将小于10的值分别交换为小于10的不同值的函数。希望对您有所帮助。
derangement <- function(x){
if(max(table(x)) > length(x)/2) return(NA)
while(TRUE){
y <- sample(x)
if(all(y != x)) return(y)
}
}
swapFun <- function(x, n = 10){
inx <- which(x < n)
y <- derangement(x[inx])
if(length(y) == 1) return(NA)
x[inx] <- y
x
}
set.seed(10)
swapFun(c(1,2,3,10,4,11,2,12))
#[1] 2 4 10 2 11 1 12
我该如何解决? 谢谢。
答案 0 :(得分:0)
对于这种大小的问题,您可以轻松使用蛮力。
在R中:
library(combinat)
pp <- permn(c(1,2,2,3)) ## construct list of permutations
pp <- unique(pp) ## unique permutations only
应用(新)约束“ x1不能为1,x2不能为2,x3不能为2,x4不能为3”:
ok <- function(X) {
!(X[1]==1 | X[2]==2 | X[3]==2 | X[4]==3)
}
pp <- pp[sapply(pp,ok)]
有length(pp)
== 2个不相同的有效组合(您可以测试length(pp)>0
是否存在剩余的有效组合)。
## define objective function
f <- function(X) { (X[1]-X[2])^2 + (X[1]-X[3])^2+
(X[2]-X[3]-X[4])^2+X[4]^2+X[3]^2 }
## compute obj function for all permutations
vals <- sapply(pp,f)
## identify minima
pp[which(vals==min(vals))]
## [[1]]
## [1] 2 3 1 2
这会随着域的增长而分解,并且(n!)的大小会变大...此时,您可能需要开始在整数编程领域进行研究(例如,请参见Optimization Task View)
在Python中,您将首先使用itertools.permutations
生成置换列表(请参见this question),然后使用理解将目标函数应用于迭代器。
答案 1 :(得分:0)
我有时将此写为一组线性分配约束:
sum(i, δ[i,j]) = 1 forall j
sum(j, δ[i,j]) = 1 forall i
x[i] = sum(j, δ[i,j] * v[j])
δ[i,j] ∈ {0,1} (binary variables)
v = [1, 2, 2, 3] (constants)
i,j ∈ {1..4} (indices}
这里δ是一个二进制变量,其性能类似于置换矩阵。