R 子矩阵的最大行列式
假设我们有一个平方矩阵R 子矩阵的最大行列式,r,matrix,optimization,determinants,cvxr,R,Matrix,Optimization,Determinants,Cvxr,假设我们有一个平方矩阵M,例如 set.seed(1) M <- matrix(rnorm(5*5), 5, 5) > M [,1] [,2] [,3] [,4] [,5] [1,] -0.6264538 -0.8204684 1.5117812 -0.04493361 0.91897737 [2,] 0.1836433 0.4874291 0.3898432 -0.01619026 0.7821
M
,例如
set.seed(1)
M <- matrix(rnorm(5*5), 5, 5)
> M
[,1] [,2] [,3] [,4] [,5]
[1,] -0.6264538 -0.8204684 1.5117812 -0.04493361 0.91897737
[2,] 0.1836433 0.4874291 0.3898432 -0.01619026 0.78213630
[3,] -0.8356286 0.7383247 -0.6212406 0.94383621 0.07456498
[4,] 1.5952808 0.5757814 -2.2146999 0.82122120 -1.98935170
[5,] 0.3295078 -0.3053884 1.1249309 0.59390132 0.61982575
我可以用蛮力的方式,也就是说,迭代所有可能的子矩阵,但我相信一定有一些优化方法可以让它更容易
我更喜欢使用
CVXR
查看解决方案,但不确定这个优化问题是否可以用凸的方式表述。有人能帮忙吗?否则,也欢迎使用其他优化包 因为已经四天没有答案了,我想我会找到一个可行的通用解决方案。不幸的是,它属于蛮力类别,尽管对于5 x 5矩阵,它相当快,大约5毫秒完成:
max_det[1]3 4 5
#>
#>$index$列
#> [1] 1 3 4
#>
#>
#>$submatrix
#> [,1] [,2] [,3]
#> [1,] -0.8356286 -0.6212406 0.9438362
#> [2,] 1.5952808 -2.2146999 0.8212212
#> [3,] 0.3295078 1.1249309 0.5939013
当然,问题是这不能很好地扩展到更大的矩阵。尽管它仍然有效:
set.seed(1)
米最大深度(米)
#>$max_行列式
#> [1] 284.5647
#>
#>美元指数
#>$index$行
#> [1] 1 3 4 5 6 8 9 10
#>
#>$index$列
#> [1] 2 3 4 6 7 8 9 10
#>
#>
#>$submatrix
#> [,1] [,2] [,3] [,4] [,5] [,6]
#> [1,] 1.51178117 0.91897737 1.35867955 0.3981059 2.40161776 0.475509529
#> [2,] -0.62124058 0.07456498 0.38767161 0.3411197 0.68973936 0.610726353
#> [3,] -2.21469989 -1.98935170 -0.05380504 -1.1293631 0.02800216 -0.934097632
#> [4,] 1.12493092 0.61982575 -1.37705956 1.4330237 -0.74327321 -1.253633400
#> [5,] -0.04493361 -0.05612874 -0.41499456 1.9803999 0.18879230 0.291446236
#> [6,] 0.94383621 -1.47075238 -0.05931340 -1.0441346 1.46555486 0.001105352
#> [7,] 0.82122120 -0.47815006 1.10002537 0.5697196 0.15325334 0.074341324
#> [8,] 0.59390132 0.41794156 0.76317575 -0.1350546 2.17261167 -0.589520946
#> [,7] [,8]
#> [1,] -0.5686687 -0.5425200
#> [2,] 1.1780870 1.1604026
#> [3,] -1.5235668 0.7002136
#> [4,] 0.5939462 1.5868335
#> [5,] 0.3329504 0.5584864
#> [6,] -0.3041839 -0.5732654
#> [7,] 0.3700188 -1.2246126
#> [8,] 0.2670988 -0.4734006
我花了一秒钟的时间来找到一个10x10矩阵的解
我认为这个解决方案是O(n!)复杂的,所以对于任何比10 x 10矩阵稍大的问题,都可以忽略它。我觉得应该有一个O(n³)解,但我的数学不够好,无法解决这个问题
我想这至少为其他人提供了一个用更复杂的方法击败的基准…我采用了艾伦·卡梅隆的解决方案,并将其与 一种启发式阈值接受(TA;一种 模拟退火)。本质上,它是从一个 随机子矩阵,然后增量更改此 子矩阵,例如通过交换行索引或 添加或删除列 解决方案将编码为列表,给出行和列索引。 因此,对于大小为5x5的矩阵,一个候选解决方案可能是
x
## [[1]]
## [1] TRUE FALSE FALSE TRUE FALSE
##
## [[2]]
## [1] TRUE FALSE TRUE FALSE FALSE
这种解决方案通过邻域函数,nb
进行更改。
例如:
nb(x)
## [[1]]
## [1] TRUE FALSE FALSE TRUE TRUE
##
## [[2]]
## [1] TRUE FALSE TRUE TRUE FALSE
## ^^^^^
给出这样一个解,我们需要一个目标函数
OF <- function(x, M)
-det(M[x[[1]], x[[2]], drop = FALSE])
本质上,nb
掷硬币,然后重新排列行或列索引(即保持子矩阵的大小不变),或者添加或删除行和列
最后,我创建了一个助手函数来创建随机初始解
x0 <- function() {
k <- sample(n, 1)
x1 <- logical(n)
x1[sample(n, k)] <- TRUE
x2 <- sample(x1)
list(x1, x2)
}
所以我们得到了相同的行/列。我进行了以下小实验,将M
的大小从2增加到20。每次我将TA的解决方案与最佳解决方案进行比较时,我还记录TA和完整枚举所需的时间(以秒为单位)
set.seed(134345)
message(format(c("Size",
"Optimum",
"TA",
"Time optimum",
"Time TA"), width = 13, justify = "right"))
for (i in 2:20) {
n <- i
M <- matrix(rnorm(n*n), n, n)
t.opt <- system.time(opt <- max_det(M)$max_determinant)
t.ta <- system.time(ta <- -restartOpt(TAopt, 10, OF,
list(x0 = x0,
neighbour = nb,
printBar = FALSE,
printDetail = FALSE,
q = 0.9,
nI = 1000, drop0 = TRUE),
M = M, best.only = TRUE)$OFvalue)
message(format(i, width = 13),
format(round(opt, 2), width = 13),
format(round(ta, 2), width = 13),
format(round(t.opt[[3]],1), width = 13),
format(round(t.ta[[3]],1), width = 13))
}
因此,至少在16x16大小之前,这两种方法返回相同的结果。但是TA需要小于1秒的恒定时间(迭代次数固定为1000)。Thomas,当你说最大行列式时,你是指行列式的最大绝对值,还是仅指最大值?i、 e.您希望从-2.2和-0.3中找出哪一个?我认为这将改变所需的方法。@AllanCameron它是最大值,而不是最大绝对值
x0 <- function() {
k <- sample(n, 1)
x1 <- logical(n)
x1[sample(n, k)] <- TRUE
x2 <- sample(x1)
list(x1, x2)
}
n <- 5
M <- matrix(rnorm(n*n), n, n)
max_det(M)$indices
## $rows
## [1] 1 2 4
##
## $columns
## [1] 2 3 5
library("NMOF")
restartOpt(TAopt, 10, OF,
list(x0 = x0,
neighbour = nb,
printBar = FALSE,
printDetail = FALSE,
q = 0.9,
nI = 1000, drop0 = TRUE),
M = M, best.only = TRUE)$xbest
## [[1]]
## [1] TRUE TRUE FALSE TRUE FALSE
##
## [[2]]
## [1] FALSE TRUE TRUE FALSE TRUE
set.seed(134345)
message(format(c("Size",
"Optimum",
"TA",
"Time optimum",
"Time TA"), width = 13, justify = "right"))
for (i in 2:20) {
n <- i
M <- matrix(rnorm(n*n), n, n)
t.opt <- system.time(opt <- max_det(M)$max_determinant)
t.ta <- system.time(ta <- -restartOpt(TAopt, 10, OF,
list(x0 = x0,
neighbour = nb,
printBar = FALSE,
printDetail = FALSE,
q = 0.9,
nI = 1000, drop0 = TRUE),
M = M, best.only = TRUE)$OFvalue)
message(format(i, width = 13),
format(round(opt, 2), width = 13),
format(round(ta, 2), width = 13),
format(round(t.opt[[3]],1), width = 13),
format(round(t.ta[[3]],1), width = 13))
}
Size Optimum TA Time optimum Time TA
2 NA 1.22 0 0.7
3 1.46 1.46 0 0.6
4 2.33 2.33 0 0.7
5 11.75 11.75 0 0.7
6 9.33 9.33 0 0.7
7 9.7 9.7 0 0.7
8 126.38 126.38 0.1 0.7
9 87.5 87.5 0.3 0.7
10 198.63 198.63 1.3 0.7
11 1019.23 1019.23 5.1 0.7
12 34753.64 34753.64 20 0.7
13 16122.22 16122.22 80.2 0.7
14 168943.9 168943.9 325.3 0.7
15 274669.6 274669.6 1320.8 0.7
16 5210298 5210298 5215.4 0.7