【问题标题】:Why is trace not preserved in tensordot为什么在tensordot中没有保留痕迹
【发布时间】:2021-07-26 22:36:40
【问题描述】:

我正在尝试取三个密度矩阵的张量积并在乘积基础中表达它。这些矩阵中的每一个都有迹线 1,理论上,乘积矩阵也应该如此。但是在 numpy 中这样做似乎会产生一些意想不到的效果。即使将中间数组重塑为二维形式也会给出相同的答案。

In [31]: rho1
Out[31]: 
array([[0. , 0. , 0. , 0. , 0. ],
       [0. , 0.1, 0. , 0. , 0. ],
       [0. , 0. , 0.2, 0. , 0. ],
       [0. , 0. , 0. , 0.3, 0. ],
       [0. , 0. , 0. , 0. , 0.4]])

In [32]: np.trace(rho1)
Out[32]: 1.0

In [33]: rho2
Out[33]: 
array([[0.2, 0. , 0. , 0. , 0. ],
       [0. , 0.2, 0. , 0. , 0. ],
       [0. , 0. , 0.2, 0. , 0. ],
       [0. , 0. , 0. , 0.2, 0. ],
       [0. , 0. , 0. , 0. , 0.2]])

In [34]: np.trace(rho2)
Out[34]: 1.0

In [35]: rho3
Out[35]: 
array([[0.5, 0. , 0. , 0. , 0. ],
       [0. , 0.5, 0. , 0. , 0. ],
       [0. , 0. , 0. , 0. , 0. ],
       [0. , 0. , 0. , 0. , 0. ],
       [0. , 0. , 0. , 0. , 0. ]])

In [36]: np.trace(rho3)
Out[36]: 1.0

In [37]: rho = np.tensordot(rho1, np.tensordot(rho2, rho3, axes=0), axes=0)

In [38]: np.trace(rho.reshape(125, 125))
Out[38]: 0.010000000000000002

In [39]: rho = np.tensordot(rho1, np.tensordot(rho2, rho3, axes=0).reshape(25,25), axes=0)

In [40]: np.trace(rho.reshape(125, 125))
Out[40]: 0.010000000000000002

我在这段代码中真的找不到任何错误,所以我觉得我误解了 tensordot 和 reshape 的工作原理。但我并没有真正从文档中得到任何东西。有人可以帮我解决这个问题吗?

【问题讨论】:

    标签: python numpy reshape tensordot


    【解决方案1】:

    简答:

    我猜你正在寻找克罗内克张量积:np.kron():

    rho = np.kron(rho1, np.kron(rho2, rho3))
    

    而这一次:

    np.trace(rho)
    Out[22]: 1.0000000000000002
    

    详情:

    为什么您的解决方案不起作用?

    因为np.reshape() 不使用“正确”维度顺序重塑您的数组,您最终可以置换某个维度以获得所需的结果:

    rho = np.moveaxis(np.tensordot(rho1, np.moveaxis(np.tensordot(rho1, rho2, axes=0),[0,1,2,3],[0,2,3,1]).reshape((5,5)), axes=0),[0,1,2,3],[0,2,3,1]).reshape((125,125))
    

    会输出正确的结果,不过既然np.kron存在,那就有点矫枉过正了。

    其实你认为np.tensordot(rho1,rho2,axes=0)相当于:

    np.einsum('ik,jl',rho1,rho2)
    

    但实际上np.tensordot(rho1,rho2,axes=0)计算:

    np.einsum('ij,kl',rho1,rho2)
    

    所以另一种获得正确答案的方法是使用:

    np.einsum('ik,jl',rho1,rho2).reshape(5,5)
    

    【讨论】:

    • 感谢np.kron 的建议!我使用 tensordot 的原因是因为它的文档说它在给定 axes=0 时给出张量积,这显然是一个“常见用例”。所以它也应该给出张量积,但可能涉及一些复杂性。
    • 是的,但是tensordot(...,axes=0) 保留了第二个参数的维度,所以它确实是张量积,但是为了您的需要,它与维度的顺序混淆了。检查我的编辑。
    【解决方案2】:

    tensordot 文档确实说 axes=0 给出了张量积:

    axes = 0 : tensor product :math:`a\otimes b`, 
    

    数组的外积。但是您必须注意生成的尺寸是如何排列的。

    但它说:

    The shape of the result consists of the non-contracted axes of the
    first tensor, followed by the non-contracted axes of the second.
    

    使用axes=0,它实际上创建了rho2[:,:,None]rho3[:,None,:],并在正常的dot 轴上求和。

    In [37]: x=np.tensordot(rho2, rho3, 0)
    In [38]: x.shape
    Out[38]: (5, 5, 5, 5)
    

    将其与einsum 与默认的“ijkl”输出进行比较:

    In [40]: y=np.einsum('ij,kl',rho2,rho3)
    In [41]: y.shape
    Out[41]: (5, 5, 5, 5)
    In [42]: np.allclose(x,y)
    Out[42]: True
    

    dot 等效项:

    In [44]: z=np.dot(rho2[:,:,None],rho3[:,None,:])
    In [45]: np.allclose(x,z)
    Out[45]: True
    

    前两个维度来自rho2

    如果您真正想要的是kron,我们必须首先转置维度,将 2 个数组中的维度交错:

    In [46]: K=np.kron(rho2,rho3)
    In [47]: K.shape
    Out[47]: (25, 25)
    In [48]: np.trace?
    In [49]: np.allclose(x.transpose(0,2,1,3).reshape(25,25),K)
    Out[49]: True
    

    测试跟踪:

    In [50]: K.trace()
    Out[50]: 1.0
    

    einsum 也一样。注意索引的顺序:

    In [53]: np.einsum('ij,kl->ikjl',rho2,rho3).reshape(25,25).trace()
    Out[53]: 1.0
    

    另一种看待这个问题的方法是从 4d 数组中提取 2d 对角线值:

    In [60]: j = np.arange(5); i=j[:,None]
    In [61]: x[i,i,j,j]
    Out[61]: 
    array([[0.1, 0.1, 0. , 0. , 0. ],
           [0.1, 0.1, 0. , 0. , 0. ],
           [0.1, 0.1, 0. , 0. , 0. ],
           [0.1, 0.1, 0. , 0. , 0. ],
           [0.1, 0.1, 0. , 0. , 0. ]])
    In [62]: _.sum()
    Out[62]: 1.0
    

    只需重塑x,将这些值放在对角线上:

    In [63]: x[i,j,i,j]
    Out[63]: 
    array([[0.1, 0. , 0. , 0. , 0. ],
           [0. , 0.1, 0. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. ]])
    

    等效于 2 步跟踪:

    In [75]: x.trace(0,0,1)
    Out[75]: 
    array([[0.5, 0. , 0. , 0. , 0. ],
           [0. , 0.5, 0. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. ],
           [0. , 0. , 0. , 0. , 0. ]])
    In [76]: x.trace(0,0,1).trace()
    Out[76]: 1.0
    

    【讨论】:

      【解决方案3】:

      np.tensordot 不是张量积,而是张量的点积。张量积类似于外积。

      【讨论】:

        猜你喜欢
        • 2010-11-04
        • 2011-01-31
        • 1970-01-01
        • 1970-01-01
        • 2020-11-17
        • 2016-04-27
        • 2011-09-09
        • 1970-01-01
        • 2013-09-07
        相关资源
        最近更新 更多