Package: ncon
nconncon is a Python 3 package that implements the NCon function as described here:https://arxiv.org/abs/1402.0939This Python implementation lacks some of the fancier features described in
the paper, but the interface is the same.ncon requires numpy and works with numpy ndarrays. It also works with the
various tensors fromthispackage,
but does not require it.Installationpip install --user nconUsageThe only thing this package exports is the functionncon. It takes a list of
tensors to be contracted, and a list index lists that specify what gets
contracted with that. It returns a single tensor, that is the result of the
contraction. Here's how the syntax works:ncon(L, v, order=None, forder=None, check_indices=True):The first argumentLis a list of tensors.
The second argumentvis a list of list, one for each tensor inL.
Eachv[i]consists of integers, each of which labels an index ofL[i].
Positive labels mark indices which are to be contracted (summed over).
So if for instancev[m][i] == 2andv[n][j] == 2, then theith index ofL[m]and thejth index ofL[n]are to be identified and summed over.
Negative labels mark indices which are to remain free (uncontracted).The keyword argumentorderis a list of all the positive labels, which
specifies the order in which the pair-wise tensor contractions are to be done.
By default it issorted(all-positive-numbers-in-v), so for instance[1,2,...]. Note that whenever an index joining two tensors is about to be
contracted together,nconcontracts at the same time all indices connecting
these two tensors, even if some of them only come up later in order.Correspondinglyforderspecifies the order to which the remaining free
indices are to be permuted. By default it issorted(all-negative-numbers-in-v, reverse=True),
meaning for instance[-1,-2,...].If bothorderandforderare provided by the user, then objects other than
integers can be used to label the indices. This has been tested with string
labels, but in principle many other types of objects should work too.Ifcheck_indices=True(the default) then checks are performed to make sure
the contraction is well-defined. If not, anValueErrorwith a helpful
description of what went wrong is provided.If the syntax sounds a lot like Einstein summation, as implemented for example
bynp.einsum, then that's because it is. The benefits ofnconare that many
tensor networkers are used to its syntax, and it is easy to dynamically
generate index lists and contractions.ExamplesHere are a few examples, straight from the test file.A matrix product:from ncon import ncon
a = np.random.randn(3, 4)
b = np.random.randn(4, 5)
ab_ncon = ncon([a, b], ((-1, 1), (1, -2)))
ab_np = np.dot(a, b)
assert np.allclose(ab_ncon, ab_np)Here the last index ofaand the first index ofbare contracted.
The result is a tensor with two free indices, labeled by-1and-2.
The one labeled with-1becomes the first index of the result. If we gave the
additional argumentforder=[-2,-1]the transpose would be returned instead.A more complicated example:b = np.random.randn(5, 3, 6, 7, 6)
c = np.random.randn(7, 2)
d = np.random.randn(8)
e = np.random.randn(8, 9)
result_ncon = ncon(
    (a, b, c, d, e), ([3, -2, 2], [2, 3, 1, 4, 1], [4, -1], [5], [5, -3])
)
result_np = np.einsum("ijk,kilml,mh,q,qp->hjp", a, b, c, d, e)
assert np.allclose(result_ncon, result_np)Notice that the network here is disconnected,dandeare not contracted
with any of the others. When contracting disconnected networks, the connected
parts are always contracted first, and their tensor product is taken at the
end. Traces are also okay, like here on two indices ofc. By default, the
contractions are done in the order [1,2,3,4,5]. This may not be the optimal
choice, in which case we should specify a better contraction order as a keyword
argument.