【问题标题】:Evaluate inner product of bra and ket in Sympy Quantum在 Sympy Quantum 中评估 bra 和 ket 的内积
【发布时间】:2019-12-31 03:44:44
【问题描述】:

在 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?

【问题讨论】:

    标签: python state sympy orthogonal


    【解决方案1】:

    您的问题是 InnerProduct 不知道如何评估这些值,因此留下了未简化的表达式。查看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 类和一个实现 2 个方法的新 Ket 类来解决您的问题 - 一个用于评估每个内部产品(使用上面规定的命名约定)。

    为了完整起见,您可能还希望为正交状态实现另一个 Ket,并确保 dual_class 在每种情况下都返回正确的类。

    【讨论】:

    • 就是这样!我复制/粘贴 boson.py 将其重命名为 OrthogonalBra/OrthogonalKet 并将内积更改为` def _eval_innerproduct_OrthogonalBra(self, bra, **hints): if self.n == bra.n: return 1 else: return 0`
    【解决方案2】:

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

    示例用法:

    >>> 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
    
    

    【讨论】:

    • sympy项目here的相关公关。
    • 谢谢,这看起来很棒!但我想还没有包含它的版本。我可以通过将定义复制粘贴到我自己的代码中来完成这项工作,但我必须包含一个.doit() 调用才能让它真正评估内部产品。没有它,我仍然得到 符号。
    • 是的,您可以在表达式上调用expr.doit()qapply(expr),类似于QM 模块中的一些其他操作。
    【解决方案3】:

    这不是您要寻找的,但您可以使用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
    

    【讨论】:

    • 感谢您的努力。不幸的是,我正在寻找一个更通用的解决方案:与qutip 一样的 N 维基础(例如:from qutip import * ket_i=basis(N,i)
    【解决方案4】:

    也许expression.xreplace() 是您要找的?根据this bookxreplace 函数可以使用字典,其中 sympy-symbols 或表达式是可散列的键。这仍然会像这样笨拙:

    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)
    

    (注意:尚未测试...)

    这至少使您可以选择在一个地方定义所有所需的替换,并在您喜欢的任何地方“重用”它们。

    【讨论】:

    • 这与问题中的替换基本相同。我想自动执行内积:sympy.Matrix([1,0,0]).dot(sympy.Matrix([0,1,0]))
    【解决方案5】:

    福克空间的答案:

    >>> 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
    

    在希尔伯特空间中是否可能发生同样的事情?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-27
      • 1970-01-01
      相关资源
      最近更新 更多