Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

Let's say I have a matrix, $\mathbf{M}$, that is polynomially dependent on a single variable, such as

M = {{15 + a^2, a + 5 a^2}, {a - 5 a^2, 2}}

and I want to find the individual matrices, $\mathbf{A}_i$, such that

$$\mathbf{M} = \mathbf{A}_0 + a \mathbf{A}_1 + a^2 \mathbf{A}_2 + \ldots$$

How do I do this? What do I use if there are multiple variables? Also, can I specify that certain symbols are not to be treated in this manner, e.g.

M = {{15 + a^2, a + 5 a^2}, {a - 5 a^2, 2 c}}

where the constant matrix would be {{15, 0}, {0, 2 c}}? Ideally, this should be applicable to vectors and tensors, also.

share|improve this question
    
Note: this is intended to be a canonical question. –  rcollyer Jun 29 '12 at 14:25
    
Consider e.g. M = {{ArcTan[a], Zeta[a]}, {Sinh[a], Sqrt[a]}}. The only route seems to be expanding every entry in Taylor series. –  Artes Jun 29 '12 at 14:35
    
@Artes you are correct, but I was honestly focusing on polynomial dependent matrices. –  rcollyer Jun 29 '12 at 14:37
    
@Artes had the right idea: Taylor coefficients are what I basically use in my answer. –  Jens Jun 29 '12 at 15:08
add comment

4 Answers

up vote 13 down vote accepted

Here is a very simple way to do it:

Table[1/i! D[M, {a, i}] /. a -> 0, {i, 0, 3}]

(*
==> {{{15, 0}, {0, 2}}, {{0, 1}, {1, 0}}, {{1, 5}, {-5, 0}}, {{0, 0}, {0, 0}}}
*)

This works even if the entries are not polynomials. If they are, you can replace the arbitrary maximum 3 in the Table index by the degree of the polynomial:

Max[Exponent[M, a]]

Edit

Looking at the other solutions, this solution (due to its fundamental simplicity) is the only one that works without modification for arbitrary rank tensors and simultaneously for arbitrary functions that can be expanded in the variable a, be they polynomial or not.

share|improve this answer
    
+1, it hadn't even occurred to me that using a derivative is perfect for this. –  rcollyer Jun 29 '12 at 15:08
2  
Alternatively: Table[Map[SeriesCoefficient[#, {a, 0, i}] &, M, {2}], {i, 0, 3}]. –  J. M. Jun 29 '12 at 15:09
    
@J.M. I think that should be posted as an answer. –  Mr.Wizard Jun 30 '12 at 7:44
1  
Accepted for simplicity and generality beyond what I asked for. –  rcollyer Jul 1 '12 at 14:06
add comment

Here's one quick way for polynomial matrices:

polyMat = {{15 + a^2, a + 5 a^2}, {a - 5 a^2, 2}};
Transpose[PadRight[CoefficientList[polyMat, a]], {2, 3, 1}]

{{{15, 0}, {0, 2}}, {{0, 1}, {1, 0}}, {{1, 5}, {-5, 0}}}

Alternatively (as Jens hints), you can do Flatten[PadRight[CoefficientList[polyMat, a]], {3}].

You can check that the matrix polynomial is reproduced with Fold[(#1 a + #2) &, 0, Reverse @ %].

share|improve this answer
    
It works (+1)... but it's a bit complicated. –  Jens Jun 29 '12 at 15:02
    
Because of the Transpose[]? ;) –  J. M. Jun 29 '12 at 15:14
    
Yes, you could have replaced Transpose by Flatten... OK - better not. –  Jens Jun 29 '12 at 15:20
    
I see. The thing is that I'm comfy with the second argument of Transpose[] for as long as I'm dealing with tensors of rank $\leq 3$. More than that, and it's a tad complicated for me to imagine, too... –  J. M. Jun 29 '12 at 15:44
    
I've modified it so that one no longer needs to deal with the polynomial degree explicitly... –  J. M. Jun 29 '12 at 18:03
add comment

First, if you don't know the degree you can compute it:

m =  {{15 + a^5, a + 5 a^2}, {a - 5 a^2, 2 c}};
degree = Max[Flatten[Exponent[#, {a}] & /@ Flatten[m]]]

(I have increased the degree of m to verify that intermediate zero matrices are correctly output.)

And now, with degree in hand, why not use a function intended for this task?

 Coefficient[m, a, #] & /@ Range[0, degree]

It works for tensors of any rank, including scalars.

share|improve this answer
    
As I mentioned in a previous version of answer, Max[Exponent[m, a] seems a bit more compact for computing the degree... –  J. M. Jun 29 '12 at 17:38
    
And, you get my last vote for today, +1. –  rcollyer Jun 29 '12 at 17:57
    
@J.M. Yes, it is more compact: thanks. (You refer to your old answer. I like the new one.) –  whuber Jun 29 '12 at 18:05
    
Yes; I fixed my comment now too... :D –  J. M. Jun 29 '12 at 18:10
add comment

This is similar to J. M.'s solution, but generalized to rank $n$ tensors.

Clear[decomposePolyMat]
decomposePolyMat[m_, var_] := 
     Module[{rank = ArrayDepth@m, coeffs = CoefficientList[m, var],len},
         len = Max@Map[Length, coeffs, {rank}];
         Flatten[Map[PadRight[#, len] &, coeffs, {rank}], {rank + 1}]
     ]
share|improve this answer
1  
Length @ Dimensions @ m is so common an operation that there is in fact a built-in function for this operation: ArrayDepth[] (formerly TensorRank[]). –  J. M. Jun 29 '12 at 15:11
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.