4
$\begingroup$

For large $n\times n$ symmetric matrices $T,$ where $n\approx10000,$ is there an efficient way of computing the total sum $S$ of its entries in Mathematica without having to loop over all its entries? i.e. $S=\sum_{i,j} t_{ij},$ for every $i,j.$ The fact that it's symmetric does help already as we only have to sum over one of its triangular parts.

$\endgroup$
  • $\begingroup$ Two quick, but very serious questions that I would really like you to think about and answer. 1: Let's just consider the upper triangular part. It seems you are thinking some efficient method won't add up some of the values. Suppose it doesn't add the first 20 rows. That would be efficient. How can it find the correct sum without those 20 rows? If it skips just one single entry, how can it give you the correct total? 2: Why is efficiency so important? People ask questions and their most important thing, is that it MUST BE EFFICIENT. Why is taking .04 seconds unacceptably inefficient? Thanks $\endgroup$ – Bill Oct 26 '19 at 17:42
  • $\begingroup$ @Bill The .04 is the time you get if you know of the highly efficient methods proposed in the answers to this question, which OP presumably didn't know about. If you approach this differently, you may end up with horribly slow code. e.g. Sum[m[[i, j]], {i, 10000}, {j, 10000}] (which may look like a reasonable solution, depending on your background) takes 38 seconds to compute the same answer. $\endgroup$ – C. E. Oct 26 '19 at 22:30
  • $\begingroup$ @Bill The point about using the symmetry of the matrix to optimize the algorithm is that you can loop over just approximately half the number of elements: tot = 0; Do[ Do[ tot += m[[i, j]], {i, j, 10} ], {j, 10} ] tot = 2 tot - Total@Diagonal[m] This is clearly preferable to looping over all the elements. Only it turns out that the most efficient way to do this, by far, is not to loop at all, but to use vectorization instead. $\endgroup$ – C. E. Oct 26 '19 at 22:40
  • $\begingroup$ @C.E. I am sincerely not being rude to anyone here. The point I was trying to make, it often takes hours for someone to get an answer to their question, but they demand that any answer MUST BE EFFICIENT, which apparently means it it is completely unacceptable to take 38 seconds to give me an answer, that would not be EFFICIENT!!! Where does this craze for efficiency come from when people who have little idea how to even begin writing any calculation need EFFICIENCY over everything else? Total[Flatten[m]] takes one second, and is not tricky code but not EFFICIENT by needing the whole matrix! $\endgroup$ – Bill Oct 27 '19 at 1:40
  • $\begingroup$ @Bill no offense taken, I completely understand your points. On the one hand, personally, I am dealing with calculations that are performed over large datasets, and without caring for efficiency might mean spending a month to post-process the data, as opposed to matter of hours! On the other hand, by posting about my problem here, my main attempt is to simply learn! Learning how I should reason about tackling such computational problems, always with an aspect of efficiency (of time and energy burnt by computers) in mind, and also how clear the approach is (...) $\endgroup$ – user52181 Oct 27 '19 at 11:30
4
$\begingroup$

Here is another solution that performs similarly to Total:

v = ConstantArray[1, 10000];
m = RandomReal[1, {10000, 10000}];
v.m.v // AbsoluteTiming

{0.040816, 4.99968*10^7}

Total[m, 2] // AbsoluteTiming

{0.041774, 4.99968*10^7}

The reason that these solutions are fast is that they use vectorization. Using Compile is not quite as fast, especially not when compiling loops:

sum = Compile[{{m, _Real, 2}},
   Sum[Compile`GetElement[m, i, j], {i, Length[m]}, {j, Length[m]}],
   CompilationTarget -> "C",
   RuntimeOptions -> "Speed"
   ];

sum[m] // AbsoluteTiming

{0.092583, 5.00016*10^7}

sum = Compile[{{m, _Real, 2}}, Module[{tot},
   tot = 0.;
   Do[
    Do[
     tot += Compile`GetElement[m, i, j],
     {i, j + 1, Length[m]}
     ],
    {j, Length[m] - 1}
    ];
   2 tot + Tr[m]
   ],
  CompilationTarget -> "C",
  RuntimeOptions -> "Speed"
  ]

sum[m] // AbsoluteTiming

{1.1837, 4.99976*10^7}

| improve this answer | |
$\endgroup$
  • $\begingroup$ Ah quite neat, thanks! I tried that but I was transposing the left v (because I was calculating $\mathbf{v}^T \mathbf{m} \mathbf{v}$) and it kept giving an error. $\endgroup$ – user52181 Oct 26 '19 at 16:40
  • $\begingroup$ @user929304 Mathematica does not distinguish between row vectors and column vectors, so the transpose is not used for such things, unlike in some software like MATLAB. Here is a good post about it. $\endgroup$ – C. E. Oct 26 '19 at 16:50
  • $\begingroup$ Thanks a lot, explains my confusion, and very much appreciate the added approaches, learned a lot! $\endgroup$ – user52181 Oct 27 '19 at 11:22
6
$\begingroup$

You can use Total. Here's a matrix of the given size:

m = RandomReal[1, {10000, 10000}];

And here's the output of Total:

Total[m, 2] // AbsoluteTiming

{0.041005, 4.99984*10^7}

| improve this answer | |
$\endgroup$
  • $\begingroup$ Thanks for the prompt answer, this is excellent! $\endgroup$ – user52181 Oct 26 '19 at 16:41
  • $\begingroup$ In general, Mathematica is set up that we almost never want to code loops (like "for" loops) when we can instead use built-in functions that treat lists and arrays as holistic objects. $\endgroup$ – Greg Martin Oct 27 '19 at 5:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy