3
$\begingroup$

I need to evaluate many times the following function: f[x_,y_]:=x*A+y*B, where x,y are real numbers and A,Bare large NxN symmetric matrices of real numbers (e.g. 1000x1000). I am trying to optimize this function. Compiling the function does not seem to help. However, as the matrices are symmetric, it is redundant to sum all the $N^2$ terms; it would be enough to sum the relevant $N(N+1)/2$ terms. Does someone know how to efficiently do this?

UPDATE: As suggested by bill s, one could store the following flatten versions of the upper triangular parts:

Aup=DeleteCases[Flatten[UpperTriangularize[A]],0]; Bup=DeleteCases[Flatten[UpperTriangularize[A]],0];

and then do: fup[x_,y_]:=x*Aup+y*Bup.

Is there an efficient way to map the vector fup[x,y] into a symmetric matrix? I have found this thread but I cannot understand well R.

$\endgroup$
  • $\begingroup$ You should make sure that your large matrices are packed using Developer`PackedArrayQ. $\endgroup$ – Carl Woll Mar 8 '17 at 19:09
  • $\begingroup$ following that, if you do the UpperTriangularize thing you need to run Developer`ToPackedArray on the result. In the end its a lot of trouble to save less than a factor of two. $\endgroup$ – george2079 Mar 8 '17 at 19:25
3
$\begingroup$

I'm not sure how much faster this will be, but you can take the upper triangular part of a, multiply that by the desired 'x' and then add that to it's transpose. Given your matrix a and value 'x'

x = 5;
atri = x UpperTriangularize[a];
atri + Transpose[atri] - DiagonalMatrix[Diagonal[atri]]

You have to subtract off the diagonal because otherwise it is added twice, once in the uppertriangular and once in the transpose. Of course you would do the same thing for b and y.

For the revised question, say you have the nonzero elements of an upper triangular matrix:

m = {{1, 2, 3, 4}, {1, 2, 3}, {1, 2}, {1}};

Then you can turn this back into a full matrix by padding at the appropriate level:

PadLeft[#, 4] & /@ m

As yode points out, if the first element of m is the full length, PadLeft[m] suffices.

$\endgroup$
  • $\begingroup$ I have tried and it takes the same time to do matrix1+matrix2 or UpperTriangularize[matrix1]+ UpperTriangularize[matrix2]. $\endgroup$ – Valerio Mar 7 '17 at 15:00
  • 1
    $\begingroup$ Another thing you could try would be to Flatten the matrix, select/take only the N(N+1)/2 important terms, do the multiplication and addition on these flattened vectors, and then Partition back to the matrix structure. This would avoid the extra additions, though at the expense of some extra indexing. $\endgroup$ – bill s Mar 7 '17 at 15:26
  • $\begingroup$ thanks, I've updated the question according to your suggestion. $\endgroup$ – Valerio Mar 8 '17 at 17:25
  • $\begingroup$ PadLeft[m] also can pad. $\endgroup$ – yode Mar 8 '17 at 18:18
  • $\begingroup$ Internal`PartitionRagged[{1, 2, 3, 4, 1, 2, 3, 1, 2, 1}, Range[4, 1, -1]] is probably needed first, and then you can just use single argument PadLeft $\endgroup$ – Carl Woll Mar 8 '17 at 18:34

Your Answer

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

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