Description
Issue with current documentation:
The docs for vdot
in NumPy 1.26 (link here) contain the following verbiage. I've emphasized some problematic text in bold.
Note that vdot handles multidimensional arrays differently than dot: it does not perform a matrix product, but flattens input arguments to 1-D vectors first. Consequently, it should only be used for vectors.
The bolded text is misleading because it doesn't account for the value of this function in computing the standard inner product on vector spaces of matrices. See below for details on this value in the cases of real and complex data.
Real matrices
If np.trace(A.T @ B)
. However, you can get the same result much more efficiently with np.vdot(A, b)
.
I see people use the naive method in their code all the time. That's bad, because the complexity difference of the two methods is stark. Here's a table comparing them. (Small disclaimer: I don't know how numpy implements vdot
in C, but the following figures are easily achievable.)
trace(A.T @ B) |
vdot(A, B) |
|
---|---|---|
time | ||
space |
Complex matrices
Now suppose
Here's a table comparing three ways one might compute this inner product. As before, I'm assuming that vdot
's C implementation doesn't have any obvious inefficiencies. I'm also assuming that calling .conj()
returns a new (conjugated) array, rather than a view of an existing array.
trace(A.T.conj() @ B) |
dot(A.conj().ravel(), B.ravel()) |
vdot(A, B) |
|
---|---|---|---|
time complexity | |||
space complexity |
Besides the complexity considerations,vdot
has a secondary advantage: it accounts for the fact that the standard inner product is conjugate-linear in the first argument and linear in the second argument. If someone isn't mindful of where they put the conjugate then it's easy to use the return value from something like `dot(A.conj().ravel(), B.ravel())`` in a way that's incorrect in the context of a larger project.
Idea or request for content:
The documentation could be updated to something like the following.
Note that vdot handles multidimensional arrays differently than dot: it does not perform a matrix product, but flattens input arguments to 1-D vectors first. The runtime of this function is linear in
a.size
andb.size
. When(a, b)
are 2-D arrays of the same shape, this function returns their Frobenius inner-product (also known as the trace inner product or the standard inner product on a vector space of matrices).