2010-07-18 89 views
29

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

因此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!

您如何执行矩阵功率操作?

回答

25

我有固定该错误在R-锻造源, SVN转( “expm” 包)。 53. - >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

0

甲^ 5 =(A^4)* A

我想库变异原变量,A,使得每个步骤涉及的结果 - 上 - 直到 - 然后乘以与原矩阵, A.你回来的结果看起来很好,只需将它们分配给一个新的变量。

+0

计算A%^%6也使A作为(初期甲 )%^%4。将结果分配给新变量不会阻止我的初始矩阵被更改。 – 2010-07-18 09:17:30

+0

听起来像是你只需先取矩阵分配到一个新的变量不寻常的一步。 – John 2010-07-18 13:01:11

2

虽然,因为它是装在一个.dll file的源代码是不是在包装可见,相信包所使用的算法是fast exponentiation algorithm,您可以通过查看功能研究称为matpowfast代替。

需要两个变量:

  1. result,为了存储输出,
  2. mat,作为中间变量。

为了计算A^6,由于6 = 110(二进制写入),在结束时,result = A^6mat = A^4。这与A^5相同。

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

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

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代码在全球环境中有副作用。

+0

它没有副作用,在全球环境 - C代码被传递到R的对象的引用,所以能够代替修改的对象。这对于某些优化是必需的,但不应该暴露给R用户。 – hadley 2010-07-19 01:58:49

+0

@hadley我明白这一点。但是,如果两个对象有一个引用(就像上面的情况,可能是为了提高效率),并且让C代码修改对象,您(我认为)会在全局环境中产生副作用,对? – 2010-07-20 00:31:29

+2

你的解释基本上是正确的,但你使用的是不是最理想的术语。在此讨论修改全球环境是没有意义的,因为该对象可能不在全球环境中。 – hadley 2010-07-20 15:30:27

2

非常快速的解决方案,而无需使用任何包使用递归性:如果你的基质是

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

HTH

+1

这不是非常有用,因为原始错误在两年前已修复...... – 2013-09-25 19:01:58

+0

加上这是对大指数执行矩阵求幂的可怕方法 – m09 2013-10-14 13:10:36