I was planning to teach np.einsum
to colleagues, by hoping to show how it would be reduced to multiplications and summations.
So, instead of numerical data, I thought to use alphabet chars. in the arrays.
Say, we have A (2X2) as [['a', 'b'], ['c', 'd']] and B (2X1) as [['e'], ['f']]
We could use einsum to create a matrix C, say like: np.einsum('ab , bc -> ac', A, B)
.
What I'd like to see is: it return the computation graph: something like: a*c + ..., etc.
Ofcourse, np.einsum
expects numerical data and would give an error if given the above code to run.
tensordot
has an example using strings for one of its arrays, taking advantage of the fact that 'a'*3 => 'aaa'
. But einsum
can't do anything with strings (tha'ts a compiled code issue).
Sometime ago I wrote a pure-python work alike, that parses the 'ij,jk->' string, and sets up the appropriate sum-of-products calculation. That includes extra debugging output. That might serve as a starting point for your task.
https://github.com/hpaulj/numpy-einsum
The latest einsum
does some optimization, with some debugging help. np.einsum_path
provides more information on that.
Understanding NumPy's einsum
https://en.wikipedia.org/wiki/Einstein_notation
First, why do you need B to be 2-dim? Why not just np.einsum('ab , b -> a', A, B)
?
Now the actual question:
It's not exactly what you want, but by using smart choices for A and B you can make this visible. e.g. A = [[1,10],[100,1000]]
and B = [1,2]
, which gives np.einsum('ab , b -> a', A, B) = [21,2100]
and it's quite obvious what has happend.
More general versions are a little bit more complicated (but hopefully not necessary). The idea is to use different potences of primes (especially useful are 2 and 5, as they align to easy readyble number in dezimal system). In case you want to sum over more than one dimesion you might consider taking primes (2,3,5,7 etc) and then convert the result into another number system.
In case you sume over two dims-> 30-ary system
3 dims (2,3,5,7)-> 210-ary system