cuquantum.cutensornet.experimental.contract_decompose¶
- cuquantum.cutensornet.experimental.contract_decompose(subscripts, *operands, algorithm=None, options=None, optimize=None, stream=None, return_info=False)[源代码]¶
评估输入操作数上收缩和分解的复合表达式。
该表达式遵循爱因斯坦求和符号进行收缩和分解符号进行分解的组合(如
decompose()
)。输入表示一个张量网络,该网络将被收缩以形成中间张量,以便进行后续分解操作,根据最终分解方法产生两个或三个输出。该表达式需要显式指定输入和输出张量的模式(不包括 SVD 方法的S
)。中间张量的模式是根据表示输出模式的下标通过使用爱因斯坦求和表达式的隐式形式推断出来的(类似于numpy.einsum
隐式模式中的处理)。请参阅注释和示例以进行澄清。
- 参数
subscripts – 模式标签(下标),用于定义收缩和分解操作,以逗号分隔的字符序列表示。表达式中允许使用 Unicode 字符,从而扩展了可以指定的张量网络的大小。
algorithm – 指定执行收缩和分解的算法。或者,可以提供一个
dict
,其中包含ContractDecomposeAlgorithm
构造函数的参数。如果未指定,则该值将设置为默认构造的ContractDecomposeAlgorithm
对象。operands – 张量序列(类 ndarray 对象)。当前支持的类型为
numpy.ndarray
、cupy.ndarray
和torch.Tensor
。options – 将张量网络的选项指定为
NetworkOptions
对象。或者,也可以提供一个dict
,其中包含NetworkOptions
构造函数的参数。如果未指定,则该值将设置为默认构造的NetworkOptions
对象。optimize – 此参数将路径优化的选项指定为
OptimizerOptions
对象。或者,也可以提供一个字典,其中包含OptimizerOptions
构造函数的参数。如果未指定,则该值将设置为默认构造的OptimizerOptions
对象。stream – 提供 CUDA 流以用于自动调优操作。可接受的输入包括
cudaStream_t
(作为 Pythonint
)、cupy.cuda.Stream
和torch.cuda.Stream
。如果未提供流,将使用当前流。return_info – 如果为 true,则有关收缩和分解的信息也将作为 :
ContractDecomposeInfo
对象返回。
- 返回
对于 QR 分解(默认),如果
return_info
为False
,则输出张量 Q 和 R(类 ndarray 对象)的类型和设备与输入操作数相同,作为分解的结果返回。如果return_info
为True
,则将返回输出张量 Q、R 和ContractDecomposeInfo
对象的三元组,其中包含有关操作的信息。对于 SVD 分解,如果
return_info
为False
,则返回输出张量 U、S 和 V(类 ndarray 对象)的三元组,其类型与输入操作数相同,作为分解的结果。如果return_info
为True
,则将返回输出张量 U、S、V 和ContractDecomposeInfo
对象的四元组,其中包含有关操作的信息。注意,根据partition
的选择,返回的 S 操作数可能为None
。另请参阅partition
。
- 返回类型
根据
algorithm
中指定的分解设置,返回的结果可能会有所不同- 引发
MemoryLimitExceeded – 执行操作所需的内存大于
options.memory_limit
收缩和分解表达式采用了爱因斯坦求和符号进行收缩和
decompose()
中引入的分解符号的组合。subscripts
字符串是下标标签的列表,其中每个标签都引用相应操作数的模式。下标标签由逗号或标识符->
分隔。标识符->
之前的下标标签被视为输入,之后的下标标签分别被视为输出。SVD 和 QR 分解的下标要求总结如下对于 SVD 和 QR 分解,下标字符串应包含多个输入和恰好两个输出标签(对于 SVD,
S
的模式不是必需的)。预计两个输出模式标签中存在一个且仅一个相同的模式。
中间张量的模式(将被分解)是根据表示输出模式的下标通过使用爱因斯坦求和表达式的隐式形式推断出来的(类似于
numpy.einsum
隐式模式中的处理)。因此,将输入模式和中间模式组合在一起应产生有效的numpy.einsum
表达式(经典或广义)。
示例
>>> # equivalent: >>> # q, r = numpy.linalg.qr(numpy.einsum('ij,jk->ik', a, b)) >>> q, r = contract_decompose('ij,jk->ix,xk', a, b)
>>> # equivalent: >>> # u, s, v = numpy.linalg.svd(numpy.einsum('ij,jk->ik', a, b), full_matrices=False) >>> u, s, v = tensor_decompose('ij,jk->ix,xk', a, algorithm={'qr_method':False, 'svd_method': {}})
对于推广到具有多维张量的通用张量网络(
a
、b
、c
均为秩为 4 的张量)。在这种情况下,中间模式ijabe
是从输出模式ixeb
和jax
推断出来的>>> # equivalent: >>> # t = contract('ijc,cad,dbe->ijabe', a, b, c) >>> # u, s, v = tensor.decompose('ijabe->ixeb,jax', t, method=SVDMethod()) >>> u, s, v = contract_decompose('ijc,cad,dbe->ixeb,jax', a, b, c, algorithm={'qr_method': False, 'svd_method': {}})
如果 contract 和 decompose 问题相当于量子电路模拟中常见的 三元操作门分裂问题 (详情请参阅 门分裂算法),用户或许可以利用
cutensornetGateSplit()
中的优化内核,方法是将门操作数放在输入操作数的最后一个。在这种情况下,QR 分解有可能被用于加速 contraction 和 SVD 的执行。这可以通过设置qr_method
和svd_method
来实现,如下所示。示例
将双量子比特门应用于相邻的 MPS 张量
>>> a, _, b = contract_decompose('ipj,jqk,pqPQ->iPx,xQk', a, b, gate, algorithm={'qr_method':{}, 'svd_method':{}})
广播 (Broadcasting) 通过省略号表示法支持某些情况。可以在输入模式中添加省略号来表示标签中未明确指定的所有模式。在这种情况下,允许在一个输出模式中最多出现一个省略号。如果一个输出模式中出现省略号,则隐式模式将被分配到相应的输出。如果在输出中没有找到省略号,则将对隐式模式求和以构建中间张量。
示例
以下是基于两个秩为 4 的张量
a
和b
的一些示例>>> # equivalent: >>> # out = contract_decompose('ijab,abcd->ijx,xcd', a, b) >>> out = contract_decompose('ijab,ab...->ijx,x...', a, b) # intermediate modes being "ijcd"
>>> # equivalent: >>> # out = contract_decompose('ijab,abcd->ix,xj', a, b) >>> out = contract_decompose('ijab,ab...->ix,xj', a, b) # intermediate modes being "ij"
>>> # equivalent: >>> # out = contract_decompose('ijab,jkab->ix,xj', a, b) >>> out = contract_decompose('ij...,jk...->ix,xj', a, b) # intermediate modes being "ij"
>>> # equivalent: >>> # out = contract_decompose('ijab,jkab->ixab,xj', a, b) >>> out = contract_decompose('ij...,jk...->ix...,xj', a, b) # intermediate modes being "ijab"
请注意,由省略号隐式表示的模式数量在所有出现的情况中必须相同。
注意
鼓励用户自行维护库句柄,以减少上下文初始化时间
from cuquantum import cutensornet as cutn from cuquantum.cutensornet.experimental import contract_decompose handle = cutn.create() q, r = contract_decompose(..., options={"handle": handle}, ...) # ... the same handle can be reused for further calls ... # when it's done, remember to destroy the handle cutn.destroy(handle)