# Create a 900x900 matrix and diagonalize it

I have to create a 900x900 matrix and then diagonalize it. It is something similar to the below matrix. The value of a,b,c,d....up to 900 values (which are the first column and row) are the number. The pattern of calculation the rest elements of the matrix is showing here (here I take an example of multiplying 3x3 matrix. the first element is a*a and so on). On top of my head, I can use Excel to calculate but it is gonna take me a long long time. Do you guys have any suggestions about the method of doing it more effectively? I would really appreciate it.

{{state, a, b, c},
{a, a*a, a*b, a*c},
{b, b*a, b*b, b*c},
{c, c*a, c*b, c*c}}

• One possibility: Outer[Times, {state, a, b, c}, {state, a, b, c}] /. {state^2 -> state, state -> 1} Only works if you don't yet have numbers, but it can be adapted. Can we get more information about the entries? Are they symbolic? NUmeric? Etc. Jul 22, 2016 at 20:59
• It looks as if your matrix will have at most rank 2. It should be possible to generate a symbolic diagonalisation for it without ever building the full matrix. It might help if you explain what you plan to do with the diagonalised form. Jul 22, 2016 at 21:04

With Times:

avec = Array[a, 4];
m = Outer[Times, avec, avec] /. {a[1] -> 1};
m[[1, 1]] = s;
MatrixForm[m]
Eigenvalues[m]


Here a[2] is your a, a[3] is your b, etc. Change the 4 to 900 if you wish. There are two nonzero eigenvalues.

• Thank you, do you have any way that I can import the value of a[n] (n from 1 to 900) from Excel. As far as I understand, for you method, I have to assign each value for a[1], a[2]...up to 900 step be step, haven't I? Jul 22, 2016 at 21:10
• Import from an excel file using Import. Jul 22, 2016 at 21:13
• yeah I know how to import it into mathematica but how to assign these 900 numbers to a[1], a[2], a[3]....a[n] at the same time instead of edit it one by one? Jul 22, 2016 at 21:18
• say your imported data is a length 900 list called dat. Then you can assign: Table[a[i] = dat[[i]], {i, 900}] Jul 22, 2016 at 21:44
• @QuangPhan Try test = Flatten[Import["Documents/test.xlsx"]]. There is an extra List for some reason. Jul 23, 2016 at 0:07
yourlist = {a, b, c};
mat = ReplacePart[Outer[Times, #, #]&@Prepend[yourlist, 1], {1, 1} -> state]


Change yourlist to the list of your interest.

Or, taking @mikado 's idea of symbolically diagonalizing:

matfunc[1, 1] = state;
matfunc[1, a_Integer] := yourlist[[a - 1]];
matfunc[a_Integer, 1] := yourlist[[a - 1]];
matfunc[a_Integer, b_Integer] := yourlist[[a - 1]] yourlist[[b - 1]];


The matrix desired is at most rank two and can be easily expressed as the product of a matrix and its transpose. I will number the elements for convenience and assume that state > 1 (otherwise we have imaginary elements, which would require further thought).

n = 3;
v1 = Prepend[Array[a, n], 1];
v2 = Prepend[Array[0 &, n], Sqrt[state - 1]];
M1 = Transpose[{v1, v2}];


The desired matrix is given by

M = M1.Transpose[M1]

(* {{state, a[1],      a[2],       a[3]},
{a[1],  a[1]^2,    a[1] a[2],  a[1] a[3]},
{a[2],  a[1] a[2], a[2]^2,     a[2] a[3]},
{a[3],  a[1] a[3], a[2] a[3],  a[3]^2}} *)


This can then be diagonalised. Symbolically this is messy so for the demonstration I will assume some arbitrary values:

testcase = {state -> 13., a[i_] -> i^2 - 7.};


The matrix M1 can be factorised using

{U, S, V} = SingularValueDecomposition[M1 /. testcase, 2];


giving M1 == U.S.Transpose[V] (for real V). Note that U and V are orthonormal and S is diagonal, so that M == M1.Transpose[M1] == U.(S.S).Transpose[U] is the diagonalisation.

This can be verified by evaluating

U.(S.S).Transpose[U] - M /. testcase // Chop
(* {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}} *)