在 Sympy Quantum 中评估 bra 和 ket 的内积

Evaluate inner product of bra and ket in Sympy Quantum

在sympy中我定义了两个kets和一个相应的文胸,当我将文胸应用到kets时...

from sympy import sqrt
from sympy.physics.quantum import Bra,Ket,qapply
superpos = (Ket('Dead')+Ket('Alive'))/sqrt(2)
d = qapply(Bra('Dead')*superpos)

...我得到这个结果:

sqrt(2)*<Dead|Alive>/2 + sqrt(2)*<Dead|Dead>/2

如何将 'Dead' 和 'Alive' 设置为正交状态,以便 d.doit() 给出 sqrt(2)/2

到目前为止,我只能用手更换刹车片:

d.subs(Bra('Dead')*Ket('Dead'),1).subs(Bra('Dead')*Ket('Alive'),0)

但是如何让括号自动求值呢?为什么 InnerProduct 对于相同的括号结果不是 1 而对于具有不同标签的括号结果不是 0?

这不是您要查找的内容,但您可以使用 Qubit 创建正交状态。

from sympy import sqrt
from sympy.physics.quantum import Dagger, qapply
from sympy.physics.quantum.qubit import Qubit

dead = Qubit(0)
alive = Qubit(1)

这些创建 Ket(0)Ket(1)。要制作文胸,您可以使用 Dagger 函数。

print(Dagger(dead) * dead)
<0|0>

应用于您的问题时:

superpos = (dead + alive) / sqrt(2)
d = qapply(Dagger(dead) * superpos)

print(d)
sqrt(2)/2

也许 expression.xreplace() 就是您要找的?根据 this bookxreplace 函数可以采用字典,其中 sympy 符号或表达式是可哈希键。这仍然很笨重:

from sympy import sqrt
from sympy.physics.quantum import Bra,Ket,qapply
superpos = (Ket('Dead')+Ket('Alive'))/sqrt(2)
d = qapply(Bra('Dead')*superpos)

mySubs = {Bra('Dead')*Ket('Dead'): 1,  Bra('Dead')*Ket('Alive'): 0} ##plus other bindings
d.xreplace(mySubs)

(注意:还没测试...)

这至少让您可以选择在一个地方定义所有需要的替换,并 "reuse" 在任何您喜欢的地方定义它们。

福克的回答space:

>>> from sympy import sqrt
>>> from sympy.physics.quantum import Dagger,qapply
>>> from sympy.physics.quantum.boson import BosonFockKet
>>> ket_Dead = BosonFockKet(0)
>>> ket_Alive = BosonFockKet(1)
>>> superpos = (ket_Dead+ket_Alive)/sqrt(2)
>>> bra_Dead = Dagger(ket_Dead)
>>> qapply(bra_Dead*superpos).doit()
sqrt(2)/2

在 Hilbert space 中也可能发生同样的事情吗?

你的问题是 InnerProduct doesn't know how to evaluate these values and so leaves the unsimplified expression instead. Looking at the source,我看到它试图在 Ket 上调用 _eval_innerproduct(),上面写着这个。

def _eval_innerproduct(self, bra, **hints):
    """Evaluate the inner product betweeen this ket and a bra.

    This is called to compute <bra|ket>, where the ket is ``self``.

    This method will dispatch to sub-methods having the format::

        ``def _eval_innerproduct_BraClass(self, **hints):``

    Subclasses should define these methods (one for each BraClass) to
    teach the ket how to take inner products with bras.
    """

因此,您应该能够通过创建 2 个新的 Bra classes 和一个实现 2 种方法的新 Ket class 来解决您的问题 - 一种用于评估每个内部产品(使用上面规定的命名约定)。

为了完整起见,您可能还想为您的正交状态实现另一个 Ket,并确保 dual_class returns 在每种情况下都是正确的 class。

正如彼得在他的回答中指出的那样,您需要自己实施新的 Bra 和 Ket class。这是一个很好的正交状态通用实现,您可以使用。

用法示例:

>>> OrthogonalBra(n)*OrthogonalKet(n)
1
>>> OrthogonalBra(n)*OrthogonalKet(n+1)
0
>>> OrthogonalBra(n)*OrthogonalKet(m)
<n|m>

实施:

class OrthogonalKet(Ket):

    @classmethod
    def dual_class(self):
        return OrthogonalBra

    def _eval_innerproduct(self, bra, **hints):

        if len(self.args) != len(bra.args):
            raise ValueError('Cannot multiply a ket that has a different number of labels.')

        for i in range(len(self.args)):
            diff = self.args[i] - bra.args[i]
            diff.simplify()

            if diff.is_nonzero:
                return 0

            if not diff.is_zero:
                return None

        return 1


class OrthogonalBra(Bra):

    @classmethod
    def dual_class(self):
        return OrthogonalKet