Exemple #1
0
def eqm_to_semi_classical(op_eqm, unresolved_ops, partition=False):
    op_factorization = {}
    sc_eqm = {}
    for op, eqm in op_eqm.items():
        sc_eqm[op] = Expectation(eqm).expand(expectation=True)

        for uop in unresolved_ops:
            sub_ops = _sceqm_factor_op(uop, op_eqm.keys())
            if sub_ops is None:
                raise Exception("Failed to find factorization of %r" % uop)
            factored_expt = Mul(*(Expectation(o) for o in sub_ops))
            op_factorization[Expectation(uop)] = factored_expt
            sc_eqm[op] = sc_eqm[op].subs(Expectation(uop), factored_expt)

    return sc_eqm, op_factorization
def normal_ordered_form(expr,
                        independent=False,
                        recursive_limit=10,
                        _recursive_depth=0):
    """Write an expression with bosonic or fermionic operators on normal
    ordered form, where each term is normally ordered. Note that this
    normal ordered form is equivalent to the original expression.

    Parameters
    ==========

    expr : expression
        The expression write on normal ordered form.

    recursive_limit : int (default 10)
        The number of allowed recursive applications of the function.

    Examples
    ========

    >>> from sympsi import Dagger
    >>> from sympsi.boson import BosonOp
    >>> from sympsi.operatorordering import normal_ordered_form
    >>> a = BosonOp("a")
    >>> normal_ordered_form(a * Dagger(a))
    1 + Dagger(a)*a
    """

    if _recursive_depth > recursive_limit:
        warnings.warn("Too many recursions, aborting")
        return expr

    if isinstance(expr, Add):
        return _normal_ordered_form_terms(expr,
                                          recursive_limit=recursive_limit,
                                          _recursive_depth=_recursive_depth,
                                          independent=independent)
    elif isinstance(expr, Mul):
        return _normal_ordered_form_factor(expr,
                                           recursive_limit=recursive_limit,
                                           _recursive_depth=_recursive_depth,
                                           independent=independent)

    elif isinstance(expr, Expectation):
        return Expectation(normal_ordered_form(expr.expression),
                           expr.is_normal_order)

    elif isinstance(expr, (Sum, Integral)):
        nargs = [
            normal_ordered_form(expr.function,
                                recursive_limit=recursive_limit,
                                _recursive_depth=_recursive_depth,
                                independent=independent)
        ]
        for lim in expr.limits:
            nargs.append(lim)
        return type(expr)(*nargs)

    else:
        return expr
def _normal_ordered_form_terms(expr,
                               independent=False,
                               recursive_limit=10,
                               _recursive_depth=0):
    """
    Helper function for normal_ordered_form: loop through each term in an
    addition expression and call _normal_ordered_form_factor to perform the
    factor to an normally ordered expression.
    """

    new_terms = []
    for term in expr.args:
        if isinstance(term, Mul):
            new_term = _normal_ordered_form_factor(
                term,
                recursive_limit=recursive_limit,
                _recursive_depth=_recursive_depth,
                independent=independent)
            new_terms.append(new_term)
        elif isinstance(term, Expectation):
            term = Expectation(normal_ordered_form(term.args[0]),
                               term.is_normal_order)
            new_terms.append(term)
        else:
            new_terms.append(term)

    return Add(*new_terms)
Exemple #4
0
def sc_eqm_to_ode(sc_eqm, t, op_label_map=None):
    op_func_map = {}
    for op in sc_eqm:
        label = repr(op) if op_label_map is None else op_label_map[op]
        op_func_map[op] = Function(label)(t)

    if debug:
        print("Operator -> Function map: ", op_func_map)

    op_subs = {Expectation(op): op_func_map[op] for op in sc_eqm}

    sc_ode = {}
    for op, eqm in sc_eqm.items():
        sc_ode[op] = Eq(Derivative(Expectation(op).subs(op_subs), t),
                        eqm.subs(op_subs))

    return sc_ode, op_func_map
Exemple #5
0
def semi_classical_eqm(H, c_ops, N=20, discard_unresolved=True):
    """
    Generate a set of semiclassical equations of motion from a Hamiltonian
    and set of collapse operators. Equations of motion for all operators that
    are included in either the Hamiltonian or the list of collapse operators
    will be generated, as well as any operators that are included in the
    equations of motion for the orignal operators. If the system of equations
    for the averages of operators does not close, the highest order operators
    will be truncated and removed from the equations.
    """
    op_eqm = {}

    ops = extract_all_operators(H + sum(c_ops))

    if debug:
        print("Hamiltonian operators: ", ops)

    t = symbols("t", positive=True)

    n = 0
    while ops:

        if n > N:
            break

        n += 1

        _, idx = min(
            (val, idx)
            for (idx, val) in enumerate([operator_order(op) for op in ops]))

        op = ops.pop(idx)

        lhs, rhs = operator_master_equation(op, t, H, c_ops, use_eq=False)

        op_eqm[op] = qsimplify(
            normal_ordered_form(rhs.doit(independent=True).expand(),
                                independent=True))

        new_ops = extract_all_operators(op_eqm[op])

        for new_op in new_ops:
            if ((not new_op.is_Number) and new_op not in op_eqm.keys()
                    and new_op not in ops):
                if debug:
                    print(new_op, "not included, adding")
                ops.append(new_op)

    if debug:
        print("unresolved ops: ", ops)

    if discard_unresolved:
        for op, eqm in op_eqm.items():
            op_eqm[op] = drop_terms_containing(op_eqm[op], ops)
        ops_unresolved = []
    else:
        ops_unresolved = ops

    #for op, eqm in op_eqm.items():
    #    for o in extract_all_operators(eqm):
    #        if o not in op_eqm.keys():
    #            print("unresolved operator: %r" % o)

    op_factorization = {}
    sc_eqm = {}
    for op, eqm in op_eqm.items():
        ops = extract_all_operators(eqm)
        sc_eqm[op] = Expectation(eqm).expand(expectation=True)

        for op2 in ops_unresolved:
            if op2 not in op_eqm.keys():
                # need to factor op2
                sub_ops = _sceqm_factor_op(op2, op_eqm.keys())
                factored_expt = Mul(*(Expectation(o) for o in sub_ops))
                op_factorization[Expectation(op2)] = factored_expt
                sc_eqm[op] = sc_eqm[op].subs(Expectation(op2), factored_expt)

    op_func_map = {}
    op_index_map = {}
    for n, op in enumerate(op_eqm):
        op_func_map[op] = Function("A%d" % n)(t)
        op_index_map[op] = n

    if debug:
        print("Operator -> Function map: ", op_func_map)

    sc_ode = {}
    for op, eqm in sc_eqm.items():
        sc_ode[op] = Eq(
            Derivative(_operator_to_func(Expectation(op), op_func_map), t),
            _operator_to_func(eqm, op_func_map))

    ops = operator_sort_by_order(op_func_map.keys())

    #for eqm in op_eqm:
    #    eqm_ops = extract_all_operators(op_eqm[op])

    SemiClassicalEQM = namedtuple('SemiClassicalEQM', [
        'operators', 'operators_unresolved', 'operator_eqs',
        'operator_factorization', 'sc_eqs', 'sc_ode', 'op_func_map',
        'op_index_map', 't'
    ])

    return SemiClassicalEQM(ops, ops_unresolved, op_eqm, op_factorization,
                            sc_eqm, sc_ode, op_func_map, op_index_map, t)
def _normal_ordered_form_factor(product,
                                independent=False,
                                recursive_limit=10,
                                _recursive_depth=0):
    """
    Helper function for normal_ordered_form_factor: Write multiplication
    expression with bosonic or fermionic operators on normally ordered form,
    using the bosonic and fermionic commutation relations. The resulting
    operator expression is equivalent to the argument, but will in general be
    a sum of operator products instead of a simple product.
    """

    factors = _expand_powers(product)

    new_factors = []
    n = 0
    while n < len(factors) - 1:

        if (isinstance(factors[n], OperatorFunction)
                and isinstance(factors[n].operator, BosonOp)):
            # boson
            if (not isinstance(factors[n + 1], OperatorFunction)
                    or (isinstance(factors[n + 1], OperatorFunction)
                        and not isinstance(factors[n + 1].operator, BosonOp))):
                new_factors.append(factors[n])

            elif factors[n].operator.is_annihilation == factors[
                    n + 1].operator.is_annihilation:
                if (independent and str(factors[n].operator.name) > str(
                        factors[n + 1].operator.name)):
                    new_factors.append(factors[n + 1])
                    new_factors.append(factors[n])
                    n += 1
                else:
                    new_factors.append(factors[n])

            elif not factors[n].operator.is_annihilation:
                new_factors.append(factors[n])

            else:
                if factors[n + 1].operator.is_annihilation:
                    new_factors.append(factors[n])
                else:
                    if factors[n].operator.args[0] != factors[
                            n + 1].operator.args[0]:
                        if independent:
                            c = 0
                        else:
                            c = Commutator(factors[n], factors[n + 1])
                        new_factors.append(factors[n + 1] * factors[n] + c)
                    else:
                        c = Commutator(factors[n], factors[n + 1])
                        new_factors.append(factors[n + 1] * factors[n] +
                                           c.doit())
                    n += 1

        elif isinstance(factors[n], Expectation):
            factor = Expectation(normal_ordered_form(factors[n].args[0]),
                                 factors[n].is_normal_order)
            new_factors.append(factor)

        elif isinstance(factors[n], BosonOp):
            # boson
            if not isinstance(factors[n + 1], BosonOp):
                new_factors.append(factors[n])

            elif factors[n].is_annihilation == factors[n + 1].is_annihilation:
                if (independent
                        and str(factors[n].name) > str(factors[n + 1].name)):
                    new_factors.append(factors[n + 1])
                    new_factors.append(factors[n])
                    n += 1
                else:
                    new_factors.append(factors[n])

            elif not factors[n].is_annihilation:
                new_factors.append(factors[n])

            else:
                if factors[n + 1].is_annihilation:
                    new_factors.append(factors[n])
                else:
                    if factors[n].args[0] != factors[n + 1].args[0]:
                        if independent:
                            c = 0
                        else:
                            c = Commutator(factors[n], factors[n + 1])
                        new_factors.append(factors[n + 1] * factors[n] + c)
                    else:
                        c = Commutator(factors[n], factors[n + 1])
                        new_factors.append(factors[n + 1] * factors[n] +
                                           c.doit())
                    n += 1

        elif isinstance(factors[n], FermionOp):
            # fermion
            if not isinstance(factors[n + 1], FermionOp):
                new_factors.append(factors[n])

            elif factors[n].is_annihilation == factors[n + 1].is_annihilation:
                if (independent
                        and str(factors[n].name) > str(factors[n + 1].name)):
                    new_factors.append(factors[n + 1])
                    new_factors.append(factors[n])
                    n += 1
                else:
                    new_factors.append(factors[n])

            elif not factors[n].is_annihilation:
                new_factors.append(factors[n])

            else:
                if factors[n + 1].is_annihilation:
                    new_factors.append(factors[n])
                else:
                    if factors[n].args[0] != factors[n + 1].args[0]:
                        if independent:
                            c = 0
                        else:
                            c = AntiCommutator(factors[n], factors[n + 1])
                        new_factors.append(-factors[n + 1] * factors[n] + c)
                    else:
                        c = AntiCommutator(factors[n], factors[n + 1])
                        new_factors.append(-factors[n + 1] * factors[n] +
                                           c.doit())
                    n += 1

        elif isinstance(factors[n], SigmaOpBase):

            if isinstance(factors[n + 1], BosonOp):
                new_factors.append(factors[n + 1])
                new_factors.append(factors[n])
                n += 1
            elif (isinstance(factors[n + 1], OperatorFunction)
                  and isinstance(factors[n + 1].operator, BosonOp)):
                new_factors.append(factors[n + 1])
                new_factors.append(factors[n])
                n += 1
            else:
                new_factors.append(factors[n])

        elif isinstance(factors[n], Operator):
            if isinstance(factors[n], (BosonOp, FermionOp)):
                if isinstance(factors[n + 1], (BosonOp, FermionOp)):
                    new_factors.append(factors[n + 1])
                    new_factors.append(factors[n])
                    n += 1
                elif (isinstance(factors[n + 1], OperatorFunction)
                      and isinstance(factors[n + 1].operator,
                                     (BosonOp, FermionOp))):
                    new_factors.append(factors[n + 1])
                    new_factors.append(factors[n])
                    n += 1
            else:
                new_factors.append(factors[n])

        elif isinstance(factors[n], OperatorFunction):

            if isinstance(factors[n].operator, (BosonOp, FermionOp)):
                if isinstance(factors[n + 1], (BosonOp, FermionOp)):
                    new_factors.append(factors[n + 1])
                    new_factors.append(factors[n])
                    n += 1
                elif (isinstance(factors[n + 1], OperatorFunction)
                      and isinstance(factors[n + 1].operator,
                                     (BosonOp, FermionOp))):
                    new_factors.append(factors[n + 1])
                    new_factors.append(factors[n])
                    n += 1
            else:
                new_factors.append(factors[n])

        else:
            new_factors.append(
                normal_ordered_form(factors[n],
                                    recursive_limit=recursive_limit,
                                    _recursive_depth=_recursive_depth + 1,
                                    independent=independent))

        n += 1

    if n == len(factors) - 1:
        new_factors.append(
            normal_ordered_form(factors[-1],
                                recursive_limit=recursive_limit,
                                _recursive_depth=_recursive_depth + 1,
                                independent=independent))

    if new_factors == factors:
        return product
    else:
        expr = Mul(*new_factors).expand()
        return normal_ordered_form(expr,
                                   recursive_limit=recursive_limit,
                                   _recursive_depth=_recursive_depth + 1,
                                   independent=independent)