Tensor and tensor network decomposition

Introduction

Decomposition methods such as QR and SVD are prevalent in tensor network algorithms, as they allow one to exploit the sparsity of the network and thus reduce the computational cost. Starting with cuQuantum Python v23.03, we provide these functionalities at both the tensor and tensor network levels. The tensor level decomposition routines are implemented inside the module cuquantum.cutensornet.tensor with the following features:

As of cuQuantum Python v23.03, the tensor network level decomposition routines are implemented in the experimental subpackage cuquantum.cutensornet.experimental with the main API cuquantum.cutensornet.experimental.contract_decompose(). Given an input tensor network, this function can perform a full contraction followed by a QR or SVD decomposition. This can be specified via cuquantum.cutensornet.experimental.ContractDecomposeAlgorithm. If the contract and decompose problem amounts to a ternary-operand gate split problem, commonly seen in quantum circuit simulation (see Gate Split Algorithm for details), the user can potentially leverage QR decompositions to speed up the execution of contraction and SVD. This can be achieved by setting both cuquantum.cutensornet.experimental.ContractDecomposeAlgorithm.qr_method and cuquantum.cutensornet.experimental.ContractDecomposeAlgorithm.svd_method.

Note

The APIs inside cuquantum.cutensornet.experimental are subject to change and may be integrated into the main package cuquantum.cutensornet in a future release. Users are encouraged to leave feedback on NVIDIA/cuQuantum GitHub Discussions.

Usage example

import cupy

from cuquantum import contract
from cuquantum.cutensornet.tensor import decompose
from cuquantum.cutensornet.experimental import contract_decompose

# create a random rank-4 tensor
a = cupy.random.random((2,2,2,2)) + cupy.random.random((2,2,2,2)) * 1j

# perform QR decomposition such that A[i,j,k,l] = \sum_{x} Q[i,x,k] R[x,j,l]
q, r = decompose('ijkl->ixk,xjl', a) # QR by default

# check the unitary property of q
identity = contract('ixk,iyk->xy', q, q.conj())
identity_reference = cupy.eye(identity.shape[0])
assert cupy.allclose(identity, identity_reference)

# check if the contraction of the decomposition outputs yields the input
a_reference = contract('ixk,xjl->ijkl', q, r)
assert cupy.allclose(a, a_reference)

More examples on tensor decompositions are available in our sample directory to demonstrate the use of QR and SVD in different settings.

For tensor network decompositions, please refer to this directory for more detailed examples. We have also provided a Jupyter notebook to demonstrate how to easily implement basic MPS algorithms using these new APIs.