Is there a numpy/scipy dot product, calculating only the diagonal entries of the result?

user2051916 picture user2051916 · Feb 7, 2013 · Viewed 11.1k times · Source

Imagine having 2 numpy arrays:

> A, A.shape = (n,p)
> B, B.shape = (p,p)

Typically p is a smaller number (p <= 200), while n can be arbitrarily large.

I am doing the following:

result = np.diag(A.dot(B).dot(A.T))

As you can see, I am keeping only the n diagonal entries, however there is an intermediate (n x n) array calculated from which only the diagonal entries are kept.

I wish for a function like diag_dot(), which only calculates the diagonal entries of the result and does not allocate the complete memory.

A result would be:

> result = diag_dot(A.dot(B), A.T)

Is there a premade functionality like this and can this be done efficiently without the need for allocating the intermediate (n x n) array?

Answer

user2051916 picture user2051916 · Feb 7, 2013

I think i got it on my own, but nevertheless will share the solution:

since getting only the diagonals of a matrix multiplication

> Z = N.diag(X.dot(Y))

is equivalent to the individual sum of the scalar product of rows of X and columns of Y, the previous statement is equivalent to:

> Z = (X * Y.T).sum(-1)

For the original variables this means:

> result = (A.dot(B) * A).sum(-1)

Please correct me if I am wrong but this should be it ...