在sympy中,定义算子对kets的已知作用,并用它来简化

2024-05-15 05:45:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一个ladder operatorâ,它以以下方式作用于ket:

â |n〉= √n |n−1〉

â⁺ |n〉= √(n+1) |n+1〉

我想用这些关系来简化更复杂的表达式,例如â⁺â²|n〉。这是我的Python代码:

import sympy
from sympy import *
from sympy.physics.quantum import *

n = symbols('n')
a = Operator('a')
ad = Dagger(a)

down = Eq( a *Ket(n), sqrt(n  )*Ket(n-1) )
up   = Eq( ad*Ket(n), sqrt(n+1)*Ket(n+1) )

expr = ad * a**2 * Ket(n)

在同形中使用已知等式的standard and most basic waysubs

但在本例中,它只对|n〉有效,而对|n+1〉或其他包含符号n的ket无效。从中可以看出 这 示例:

In[1]: expr.subs( down.lhs, down.rhs ).subs( down.lhs, down.rhs ).subs( up.lhs, up.rhs )

Out[1]: √n â⁺ â |n−1〉


Tags: fromimportsqrtadeqdownsubssympy
1条回答
网友
1楼 · 发布于 2024-05-15 05:45:23

我自己写了一个简单的算法,取得了最好的效果。该算法与this answer中的算法非常相似,您可以这样使用它:

expr.apply_operator(down,up).factor()

结果

√n (n−1) |n−1〉

该算法只支持“纯”算子(没有任何运算)和左侧的伴随算子。例如,通过对is_operatoris_expandable_pow_of进行一些小的修改,可以扩展算法,以允许在左侧使用逆运算符

from sympy.core.operations import AssocOp

def apply_operator(expr, eqns):
    if not isinstance(expr, Basic):
        raise TypeError("The expression to simplify is not a sympy expression.")

    if not isinstance(eqns, list) and not isinstance(eqns, tuple):
        eqns = (eqns,)


    rules = []


    class Rule(object):
        operator = None
        ketSymbol = None
        result = None
        generic = False


    def is_operator(op):
        return isinstance(op, Operator) \
        or isinstance(op, Dagger) \
        and isinstance(op.args[0], Operator)


    for eqn in eqns:
        if not isinstance(eqn, Eq):
            raise TypeError("One of the equations is not a valid sympy equation.")

        lhs = eqn.lhs
        rhs = eqn.rhs

        if not isinstance(lhs, Mul) \
        or len(lhs.args) != 2 \
        or not is_operator(lhs.args[0]) \
        or not isinstance(lhs.args[1], KetBase):
            raise ValueError("The left-hand side has to be an operator applied to a ket.")

        rule = Rule()
        rule.operator = lhs.args[0]
        rule.ketSymbol = lhs.args[1].args[0]
        rule.result = rhs

        if not isinstance(rule.ketSymbol, Symbol):
            raise ValueError("The left-hand ket has to contain a simple symbol.")

        for ket in preorder_traversal(rhs):
            if isinstance(ket, KetBase):
                for symb in preorder_traversal(ket):
                    if symb == rule.ketSymbol:
                        rule.generic = True
                        break

        rules.append(rule)


    def is_expandable_pow_of(base, expr):
        return isinstance(expr, Pow) \
            and base == expr.args[0] \
            and isinstance(expr.args[1], Number) \
            and expr.args[1] >= 1


    def is_ket_of_rule(ket, rule):
        if not isinstance(ket, KetBase):
            return False

        if rule.generic:
            for sym in preorder_traversal(ket):
                if sym == rule.ketSymbol:
                    return True
            return False

        else:
            return ket.args[0] == rule.ketSymbol


    def walk_tree(expr):
        if isinstance(expr, Number):
            return expr

        if not isinstance(expr, AssocOp) and not isinstance(expr, Function):
            return expr.copy()

        elif not isinstance(expr, Mul):
            return expr.func(*(walk_tree(node) for node in expr.args))

        else:
            args = [arg for arg in expr.args]

            for rule in rules:
                A = rule.operator
                ketSym = rule.ketSymbol

                for i in range(len(args)-1):
                    x = args[i]
                    y = args[i+1]

                    if A == x and is_ket_of_rule(y, rule):
                        ev = rule.result

                        if rule.generic:
                            ev = ev.subs(rule.ketSymbol, y.args[0])

                        args = args[0:i] + [ev] + args[i+2:]
                        return walk_tree( Mul(*args).expand() )

                    if is_expandable_pow_of(A, x) and is_ket_of_rule(y, rule):
                        xpow = Pow(A, x.args[1] - 1)
                        ev = rule.result

                        if rule.generic:
                            ev = ev.subs(rule.ketSymbol, y.args[0])

                        args = args[0:i] + [xpow, ev] + args[i+2:]
                        return walk_tree( Mul(*args).expand() )


            return expr.copy()


    return walk_tree(expr)


Basic.apply_operator = lambda self, *eqns: apply_operator(self, eqns)

(No rights reserved.)

相关问题 更多 >

    热门问题