R中的矩阵功率

时间:2010-07-18 08:22:14

标签: r matrix linear-algebra

尝试计算R中矩阵的幂,我发现包expm实现了运算符%^%

因此x%^%k计算矩阵的k次方。

> A<-matrix(c(1,3,0,2,8,4,1,1,1),nrow=3)

> A %^% 5
      [,1]  [,2] [,3]
[1,]  6469 18038 2929
[2,] 21837 60902 9889
[3,] 10440 29116 4729

但令我惊讶的是:

> A
     [,1] [,2] [,3]
[1,]  691 1926  312
[2,] 2331 6502 1056
[3,] 1116 3108  505

不知何故,初始矩阵A已变为A%^%4 !!!

如何执行矩阵功率操作?

7 个答案:

答案 0 :(得分:29)

我修复了R-forge源(“expm”包)中的错误, svn rev。 53. - &gt; expm R-forge page 由于某种原因,网页仍然显示rev.52,因此以下可能还没有 解决你的问题(但应该在24小时内):

 install.packages("expm", repos="http://R-Forge.R-project.org")

否则,直接获取svn版本并自行安装:

 svn checkout svn://svn.r-forge.r-project.org/svnroot/expm

感谢“gd047”通过电子邮件提醒我这个问题。 请注意,R-forge也有自己的错误跟踪功能 Martint

答案 1 :(得分:8)

这不是一个正确的答案,但可能是讨论和理解R的内部工作的好地方。这种错误已经在我正在使用的另一个包中出现过。

首先,请注意,首先简单地将矩阵分配给新变量没有帮助:

> A <- B <-matrix(c(1,3,0,2,8,4,1,1,1),nrow=3)
> r1 <- A %^% 5
> A
     [,1] [,2] [,3]
[1,]  691 1926  312
[2,] 2331 6502 1056
[3,] 1116 3108  505
> B
     [,1] [,2] [,3]
[1,]  691 1926  312
[2,] 2331 6502 1056
[3,] 1116 3108  505

我的猜测是R试图通过引用而不是值来进行智能传递。要真正实现这一点,您需要做一些事情来区分A和B:

`%m%` <- function(x, k) {
    tmp <- x*1
    res <- tmp%^%k
    res
}
> B <-matrix(c(1,3,0,2,8,4,1,1,1),nrow=3)
> r2 <- B %m% 5
> B
     [,1] [,2] [,3]
[1,]    1    2    1
[2,]    3    8    1
[3,]    0    4    1

这样做的明确方法是什么?

最后,在包的C代码中,有这样的评论:

  • 注意:x会被改变!如果需要,来电者必须制作副本

但我不明白为什么R让C / Fortran代码在全球环境中产生副作用。

答案 2 :(得分:2)

虽然源代码在包中不可见,因为它打包在.dll file中,我相信包使用的算法是fast exponentiation algorithm,您可以通过查看而是名为matpowfast的函数。

您需要两个变量:

  1. result,为了存储输出,
  2. mat,作为中间变量。
  3. 要计算A^6,自6 = 110(二进制书写),最后result = A^6mat = A^4。这与A^5相同。

    当您尝试为任何mat = A^8计算A^n时,您可以轻松检查8<n<16。如果是这样,你有解释。

    包函数使用初始变量A作为中间变量mat

答案 3 :(得分:2)

非常快速的解决方案不使用任何软件包使用递归: 如果您的矩阵是

 powA = function(n)
 {
    if (n==1)  return (a)
    if (n==2)  return (a%*%a)
    if (n>2) return ( a%*%powA(n-1))
 }

HTH

答案 4 :(得分:0)

A ^ 5 =(A ^ 4)* A

我想这个库会改变原始变量A,所以每一步都需要将结果直到当时的矩阵A相乘。你得到的结果看起来很好,只需将它们分配给一个新的变量

答案 5 :(得分:0)

base中的效率低下的版本(因为首先对角线化矩阵效率更高)是:

pow = function(x, n) Reduce(`%*%`, replicate(n, x, simplify = FALSE))

我知道这个问题专门与expm中的一个旧错误有关,但是这是目前“矩阵幂R”的第一个结果,因此希望这个简短的缩写可以对其他结局的人有用在这里只是寻找一种无需安装任何程序包即可运行矩阵电源的快速方法。

答案 6 :(得分:0)

您可以简单地使用特征值和特征向量来计算矩阵的指数;

# for a given matrix, A of power n

eig_vectors <- eigen(A)$vectors
eig_values <- eigen(A)$values

eig_vectors %*% diag(eig_values)^n %*% solve(eig_vectors)

或者来自 @MichaelChirico 的改进答案。矩阵的 exponent 0 将返回其单位矩阵而不是 NULL

pow = function(x, n) {
    if (n == 0) {
        I <- diag(length(diag(x)))
        return(I)        
    } 
    Reduce(`%*%`, replicate(n, x, simplify = FALSE))    
}
相关问题