web-dev-qa-db-fra.com

Puissance matricielle en R

En essayant de calculer la puissance d’une matrice dans R, j’ai trouvé que le paquetage expm implémentait l’opérateur % ^%

Donc x% ^% k calcule la k-ème puissance d'une matrice. 

> 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

mais, à ma grande surprise:

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

en quelque sorte, la matrice initiale A a été remplacée par A% ^% 4 !!!

Comment effectuez-vous l'opération d'alimentation matrice?

30
George Dontas

J'ai corrigé ce bogue dans les sources R-forge (du paquet "expm"), Svn rev. 53. -> expm Page R-forge Pour une raison quelconque, la page Web affiche toujours la rév.52, aussi ce qui suit ne résoudra peut-être pas encore votre problème (mais devrait le faire dans les 24 heures): 

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

Sinon, récupérez directement la version de svn et installez vous-même: 

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

Merci à "Gd047" qui m'a alerté sur le problème par courrier électronique . Notez que R-forge possède également ses propres fonctionnalités de suivi des bogues.
Martint

29
Martin Mächler

Ce n'est pas une bonne réponse, mais c'est peut-être un bon endroit pour avoir cette discussion et comprendre le fonctionnement interne de R. Ce genre de bogue s'est déjà glissé dans un autre paquet que j'utilisais.

Tout d’abord, notez que l’affectation de la matrice à une nouvelle variable n’aide en rien:

> 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

Je suppose que R essaie d’être intelligent en passant par référence plutôt que par valeur. Pour que cela fonctionne, vous devez faire quelque chose pour différencier A de 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

Quelle est la manière explicite de faire cela?

Enfin, dans le code C du paquet, il y a ce commentaire:

  • NB: x sera modifié! L'appelant doit faire une copie si nécessaire

Mais je ne comprends pas pourquoi R laisse le code C/Fortran avoir des effets secondaires dans l’environnement mondial.

8
Eduardo Leoni

Solution très rapide sans utiliser aucun package utilise la récursivité: Si votre matrice est un 

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

HTH

2
DKK

Bien que le code source ne soit pas visible dans le paquet car il est emballé dans un .dll file, je crois que l'algorithme utilisé par le paquet est l'algorithme exponentiation rapide , que vous pouvez étudier en regardant plutôt la fonction matpowfast.

Vous avez besoin de deux variables:

  1. result, afin de stocker la sortie,
  2. mat, en tant que variable intermédiaire.

Pour calculer A^6, depuis 6 = 110 (écriture binaire), à ​​la fin, result = A^6 et mat = A^4. C'est la même chose pour A^5.

Vous pouvez facilement vérifier si mat = A^8 lorsque vous essayez de calculer A^n pour tout 8<n<16. Si oui, vous avez votre explication.

La fonction de package utilise la variable initiale A comme variable intermédiaire mat.

2
Wok

A ^ 5 = (A ^ 4) * A

Je suppose que la bibliothèque mute la variable d'origine, A, de sorte que chaque étape implique la multiplication du résultat avec la matrice d'origine, A. Le résultat obtenu semble correct, affectez-le à une nouvelle variable.

0
Michiel