# Order of evaluation

I am having a hard time figuring this out:

( sample ) I have any matrix which can have an arbitrarily large dimension.

mat = SparseArray[Automatic, {4, 4},
0., {1, {{0, 1, 3, 5, 6}, {{2}, {1}, {3}, {4}, {2}, {3}}},
{5.4*Cos[1.23*x], 5.4*Cos[1.23*x], 2.7, 5.4*Cos[1.23*x], 2.7,
5.4*Cos[1.23*x]}}];(*4X4 matrix*)
eign[x_] := Eigensystem[mat]
evec[x_] := eign[x][[2]];


I find it hard to understand the evaluation order when I try to evaluate the function. Say, I want to find eval at x=1;

I try,

evec[1]
(* Unable to find all eigenvectors.
Out[128]= {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}*)

Table[evec[x], {x, 1}]
(*{{{0.316639, 0.63225, 0.63225, 0.316639}, {0.316639, -0.63225,  0.63225, -0.316639}, {0.63225,  0.316639, -0.316639, -0.63225}, {0.63225, -0.316639, -0.316639, 0.63225}}}*)

Table[evec[y], {y, 1}]
(* Unable to find all eigenvectors.
Out[128]= {{0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}, {0, 0, 0, 0}}*)


Can someone explain me what's going on in all three processes and why the 2nd one gives the value but not others. what's the most efficient way of obtaining value at any x value? Thank you

(Note: Set-delayed in the expression can't be removed if the matrix is large and complex. i.e. analytical eigensystem isn't possible in those problems. So, Evaluate can't be used for those while defining the functions either )

I think it has something to do with the xs in your mat. Probably when you use Table[evec[x], {x, 1}] it somehow replaces the x with 1, but it doesn't make that replacement when you use other variables.

Certainly when you use evec[1], this calls eign[1], but eign can't actually do anything with its argument because mat has already been defined previously. Try making mat a function so that it evaluates only once you've assigned a value to x.

mat[x_] :=
SparseArray[Automatic, {4, 4},
0., {1, {{0, 1, 3, 5, 6}, {{2}, {1}, {3}, {4}, {2}, {3}}}, {5.4*
Cos[1.23*x], 5.4*Cos[1.23*x], 2.7, 5.4*Cos[1.23*x], 2.7,
5.4*Cos[1.23*x]}}]
eign[x_] := Eigensystem[mat[x]]
evec[x_] := eign[x][[2]]
evec[1]


$$\left( \begin{array}{cccc} 0.316639 & 0.63225 & 0.63225 & 0.316639 \\ 0.316639 & -0.63225 & 0.63225 & -0.316639 \\ 0.63225 & 0.316639 & -0.316639 & -0.63225 \\ 0.63225 & -0.316639 & -0.316639 & 0.63225 \\ \end{array} \right)$$

Edit:

I'm not sure if this suits your use case or not, but if you're importing a matrix from outside that has a variable, you could use ReplaceAll (/.) to replace the variable(s) just once, then you don't have to have SetDelayed.

importMatrix = (* external matrix with x in it *);
mat[var_]:= mat[var] = importMatrix/.{x -> var}
eign[x_] := Eigensystem[mat[x]]
evec[x_] := eign[x][[2]]


I'm not sure if you need it or not, but mat[var_] := mat[var] = ... means that if you call mat[1] at some point, it will insert 1 into the matrix anywhere it sees x, and then store the result in the variable mat[1]. This means that it only ever has to be done once for each variable. If you're going to call mat many times with many different values, it should probably just be the function itself without the extra mat[var] otherwise it will take up a lot of memory.

ReplaceAll works on regular matrices, but doesn't work directly on sparse matrices, which is why I was asking whether they could be made into normal matrices. If they are imported, I assume that they are. Also, here is the link I actually meant to post earlier.

Let me know if I'm still misunderstanding your use case; I might be able to help, and if I can't, there are definitely people here who can.

• But, say you have a huge matrix that is saved in some value. It's often impossible to write down all the matrix in set-delayed rather than simply defining it as mat[x_] =matrix (matrix being fairly large and evaluated through a lot of calculations). Any Idea of how to call a variable other than pasting a whole element. Commented Jun 4, 2020 at 23:10
• @maeinss It certainly can be done. The best method for doing that may depend on exactly how large your matrices are. The easiest way would be if you can convert your SparseArray back to a normal array. Is your matrix too large or unwieldy to fit into memory? If you think it'll be too big, let me know. This question has some information on how to do it without turning it back into a normal array, so I think I can come up with something. Commented Jun 5, 2020 at 1:22
• @maeinss Ultimately, I'm not sure that using Set actually accomplishes what you want. If you just want the matrix to be evaluated once so that you're not re-evaluating it every time, that could be accomplished by memoization. Commented Jun 5, 2020 at 1:25
• Thanks.Did you put any external link on 'This'? If so maybe you forgot the url. I usually create the matrix working with sparseArray and Band and dimension can go pretty high. For my problem in particular, I can put setdelayed right at the beginning when constructing a matrix and express it as a function of x which will solve the problem. But, If I am to export some matrix generated from outside, that's why I am asking. I appreciate your willingness to help. Commented Jun 5, 2020 at 1:38
• @maeinss Whoops, I pasted the wrong link. I've edited the question. Take a look and see if it helps at all. Commented Jun 5, 2020 at 3:22