Skip to content

Input Format

The opt_einsum package was originally designed as a drop-in replacement for the np.einsum function and supports all input formats that np.einsum supports. There are two styles of input accepted, a basic introduction to which can be found in the documentation for numpy.einsum. In addition to this, opt_einsum extends the allowed index labels to unicode or arbitrary hashable, comparable objects in order to handle large contractions with many indices.

'Equation' Input

As with numpy.einsum, here you specify an equation as a string, followed by the array arguments:

import opt_einsum as oe
eq = 'ijk,jkl->li'
x, y = np.random.rand(2, 3, 4), np.random.rand(3, 4, 5)
z = oe.contract(eq, x, y)
z.shape
#> (5, 2)

However, in addition to the standard alphabet, opt_einsum also supports unicode characters:

eq = "αβγ,βγδ->δα"
oe.contract(eq, x, y).shape
#> (5, 2)

This enables access to thousands of possible index labels. One way to access these programmatically is through the function get_symbols:

oe.get_symbol(805)
#> 'α'

which maps an int to a unicode characater. Note that as with numpy.einsum if the output is not specified with -> it will default to the sorted order of all indices appearing once:

eq = "αβγ,βγδ"  # "->αδ" is implicit
oe.contract(eq, x, y).shape
#> (2, 5)

'Interleaved' Input

The other input format is to 'interleave' the array arguments with their index labels ('subscripts') in pairs, optionally specifying the output indices as a final argument. As with numpy.einsum, integers are allowed as these index labels:

oe.contract(x, [1, 2, 3], y, [2, 3, 4], [4, 1]).shape
#> (5, 2)

with the default output order again specified by the sorted order of indices appearing once. However, unlike numpy.einsum, in opt_einsum you can also put anything hashable and comparable such as str in the subscript list. A simple example of this syntax is:

x, y, z = np.ones((1, 2)), np.ones((2, 2)), np.ones((2, 1))
oe.contract(x, ('left', 'bond1'), y, ('bond1', 'bond2'), z, ('bond2', 'right'), ('left', 'right'))
#> array([[4.]])

The subscripts need to be hashable so that opt_einsum can efficiently process them, and they should also be comparable so as to allow a default sorted output. For example:

x = np.array([[0, 1], [2, 0]])

# original matrix
oe.contract(x, (0, 1))
#> array([[0, 1],
#>        [2, 0]])

# the transpose
oe.contract(x, (1, 0))
#> array([[0, 2],
#>        [1, 0]])

# original matrix, consistent behavior
oe.contract(x, ('a', 'b'))
#> array([[0, 1],
#>        [2, 0]])

# the transpose, consistent behavior
>>> oe.contract(x, ('b', 'a'))
#> array([[0, 2],
#>        [1, 0]])

# relative sequence undefined, can't determine output
>>> oe.contract(x, (0, 'a'))
#> TypeError: For this input type lists must contain either Ellipsis
#> or hashable and comparable object (e.g. int, str)