MatrixPower[]
- To: mathgroup at smc.vnet.net
- Subject: [mg28919] MatrixPower[]
- From: Konstantin L Kouptsov <klk206 at nyu.edu>
- Date: Fri, 18 May 2001 01:13:26 -0400 (EDT)
- Organization: New York University
- Sender: owner-wri-mathgroup at wolfram.com
Hello, Mathgroup, I needed to calculate the n-th power of a given matrix M. Usually it can be done with the MatrixPower[M,n] function. But for the symbolic power it becomes a bit tricky. Take M={{1,1,1},{0,1,0},{1,1,1}}, then MatrixPower[M,n] gives {{2^(-1+n),-1+2^n,2^(-1+n)}, {0, 1,0}, {2^(-1+ n),-1+2^n,2^(-1+n)}} Now, if you change the matrix to M={{1,1,1},{0,2,0},{1,1,1}}, then the MatrixPower function gives an error MatrixPower::"zvec": "Cannot compute MatrixPower because the argument has a zero eigenvector." which seems irrelevant, since the power of a square matrix always exist. The reason for this error is in the way Mathematica calculates the power. Here is the explicit form of the used algorithm {eval, evec} = Eigensystem[M0]; s = Transpose[evec]; A = DiagonalMatrix[eval]; M[n_] := s.MatrixPower[A, n].Inverse[s] which of course does not work if s has no inverse. To circumvent the problem one can use the Hamilton-Cailey theorem (which can be found in the Korn,Korn mathematical handbook). The theorem gives a recipe to calculate any function of a matrix using Vandermonde matrix built on its eigenvalues and a finite number of powers of the matrix itself. Below is the implementation of this theorem. There is one thing to watch out: it the matrix has equal eigenvalues, the Vandermonde matrix is zero, so you get indeterminate 0/0. The way the theorem can be applied is that you can resolve indeterminancy by cancelling out zeroes in numerator and denominator, as in (2-2)(7-5) 1 __________ = _ (2-2)(9-3) 3 which must be done in mathematically correct way (remember calculus?) I used the function ReplaceEqual[] to discern the similar eigevalues in the following manner: ReplaceEqual[{1,1,2,3,4,4,5}] gives {{1,1+i1,2,3,4,4+i2,5},{i1,i2}} i.e. shift similar eigenvalues to make them different, and at the end calculate the result by setting i1,i2 to zero. This is done by the following code ReplaceEqual[x_List] := Module[{i = 1, a, k, ls1 = {}, ls2, s, x1}, x1 = Sort[x]; a = First[x1]; ls2 = List[a]; For[k = 2, k <= Length[x1], k++, If[x1[[k]] == a, s = ToExpression["i" <> ToString[i++]]; AppendTo[ls2, x1[[k]] + s]; AppendTo[ls1, s], AppendTo[ls2, x1[[k]]]; a = x1[[k]] ] ]; {ls2, ls1} ] Now the Vandermonde matrix determinant can be calculated in a rather efficient way VandermondeMatrix[eval_List] := Module[{x, y}, x = Table[1, {Length[eval]}]; y = (eval^# &) /@ Range[1, Length[eval] - 1]; PrependTo[y, x] ] but we also need the determinant of the Vandermonde matrix with one of the columns replaced by {F[eval[[1]]],F[eval[[2]]],...} VandermondeMatrixReplaced[eval_List,f_, n_] := Module[{w, fs}, w = VandermondeMatrix[eval]; (* or pull this call out for efficiency *) fs = Map[f, eval]; ReplacePart[w, fs, n] ] Calculation of this deteminant was a problem which caused my recent messages to MathGroup. Rasmus Debitsch have suggested using the row echelon form of the matrix. For smaller matrices simple Det[] works. Finally we arrive at the HamiltonCailey[] function which computes any function of a square matrix: HamiltonCailey[A_, F_] := Module[{eig, n, w, wr, x}, {eig, vars} = ReplaceEqual[Eigenvalues[A]]; n = Dim[A]; (* dimension of the n x n matrix A *) w = VandermondeMatrix[eig]; wr = (1/Det[w]) Sum[ Det[VandermondeMatrixReplaced[eig, F, n - k + 1]]* MatrixPower[A, n - k], {k, 1, n}] ] Do not forget to apply the Limit[] to the result. There is still a lot to be said about the above method, but you get the idea. For the matrix in above example M={{1,1,1},{0,2,0},{1,1,1}} you write Limit[HamiltonCailey[M,#^n&]//Simplify,i1->0] to get the answer {{2^(-1+n),n 2^(-1+n),2^(-1+n)}, {0,2^n,0}, {2^(-1+n),n 2^(-1+n),2^(-1+n)}} Konstantin. PS. I wish to thank Rasmus Debitsch and all who responded to my post.
- Follow-Ups:
- Re: MatrixPower[]
- From: Daniel Lichtblau <danl@wolfram.com>
- Re: MatrixPower[]