I want to efficiently perform a chain of matrix-vector multiplication in Python and the numpy.einsum function seems to be the best choice. However, I do NOT know the number of matrix operands N in the chain a priori and so there is no simple way to write the subscripts string to pass to einsum.
To be more clear, let's consider the simple case with N=3 matrices A, B, and C and the initial vector v. The numpy.einsum call would be the following:
result = numpy.einsum('ij,jk,kl,l', A, B, C, v)
How can I generalize this operation to an arbitrary N? A possibility would be to programmatically create the subscripts string but numpy.einsum only supports 52 different labels (26 letters lower and upper case) and this represents a limitation in my case since I don't know a priori the number of operands.
Is there maybe a way to do this as efficiently as possible by using another approach based on a different numpy function?
As mentioned in the comments, you can use the (undocumented?) interleaved mode to facilitate generating your subscripts. Something like this:
This should work up to ~50 according to a bugfix from 2018, however it doesn't work for me above ~30.
As suggested by @learning-is-a-mess, you could also do it in blocks: split your list of matrices into N sized blocks, run each block through
einsumwith the previous block's output as its first input.The best option, though, is probably just to use
opt_einsum. This can significantly speed up youreinsum, and also supports arbitrary numbers of indices: