这个问题在参考时来自code-golf challenge.
的观察提交的R解决方案是一个有效的解决方案,但我们中的一些人(可能只是我)似乎对为什么需要进行初始X=m
重新分配感到茫然。
@Giuseppe对代码进行了一些打击,所以我会给读者写一些评论。
function(m){
X=m
# Re-assign input m as X
while(any(X-(X=X%*%m))) 0
# Instead of doing the meat of the calculation in the code block after `while`
# OP exploited its infinite looping properties to perform the
# calculations within the condition check.
# `-` here is an abuse of inequality check and relies on `any` to coerce
# the numeric to logical. See `as.logical(.Machine$double.xmin)`
# The code basically multiplies the matrix `X` with the starting matrix `m`
# Until the condition is met: X == X%*%m
X
# Return result
}
据我所知。乘以X%*%m
相当于X%*%X
,因为X
只是m
的迭代自乘版本。矩阵收敛后,乘以m
或X
的其他副本不会改变其值。将上述函数定义为v(m)%*%v(m)%*%v(m)%*%v(m)%*%v(m)%*%m%*%m
后,请参阅线性代数教科书或v
。好吗?
所以问题是,为什么@ CodesInChaos实现这个想法不起作用?
function(m){while(any(m!=(m=m%*%m)))0 m}
这是由浮点精度问题引起的吗?或者这是由代码中的函数引起的,例如不等式检查或.Primitive(“any”)?我不认为这是由as.logical
引起的,因为R似乎强制将小于.Machine$double.xmin
的错误强制为0。
以上是对此的演示。我们只是循环并在m
和m%*%m
之间取得差异。当我们试图收敛随机矩阵时,该误差变为0。它似乎收敛然后根据输入最终吹到0 / INF。
mat = matrix(c(7/10, 4/10, 3/10, 6/10), 2, 2, byrow = T)
m = mat
for (i in 1:25) {
m = m%*%m
cat("Mean Error:", mean(m-(m=m%*%m)),
"\n Float to Logical:", as.logical(m-(m=m%*%m)),
"\n iter", i, "\n")
}
关于为什么这是浮点数学问题的一些额外想法
1)循环表明这可能不是any
或任何逻辑检查/转换步骤的问题,而是与浮点矩阵数学有关。
2)@ user202729在原始帖子中评论这个问题在Jelly中仍然存在,代码高尔夫语言让人更加相信这可能是一个浮点问题。
答案 0 :(得分:5)
不同的方法迭代不同的函数,都以种子值m
开头。如果该固定点是稳定的并且种子在该固定点的吸引范围内,则函数迭代仅收敛到给定的固定点。
在原始代码中,您正在迭代函数
f <- function(X) X %*% m
极限矩阵是一个稳定的定点,在假设下(代码湾问题中说明)存在明确的限制。由于函数定义取决于m
,因此固定点是m
的函数并不令人惊讶。
另一方面,使用m = m %*% m
的建议变体是通过迭代函数
g <- function(X) X %*% X
请注意,所有幂等矩阵都是此函数的固定点,但很明显它们都不是稳定的固定点。显然,原始固定函数中的限制矩阵不是g
的稳定不动点(即使它是一个固定点)。
要真正解决这个问题,你需要在函数迭代下进入矩阵不动点理论,以显示为什么 g
不稳定时的固定点。
答案 1 :(得分:-1)
这确实是一个浮点数学问题。要查看它,请参阅此函数的结果:
test2 <- function(m) {
c <- 0
res <- list()
while (any(m!=(m=m%*%m))) {
c <- c + 1
res[[c]] <- m
}
print(c)
res
}
要测试具有一定容差的相等性,您可以使用:
test3 <- function(m) {
while (!isTRUE(all.equal(m, m <- m %*% m))) 0
m
}