def test_density():
    d = Density([Jz * mo, 0.5], [Jz * po, 0.5])
    assert qapply(d) == Density([-hbar * mo, 0.5], [hbar * po, 0.5])
Пример #2
0
def test_apply_op():
    d = Density([Ket(0), 0.5], [Ket(1), 0.5])
    assert d.apply_op(XOp()) == Density([XOp() * Ket(0), 0.5],
                                        [XOp() * Ket(1), 0.5])
Пример #3
0
def test_eval_trace():
    q1 = Qubit('10110')
    q2 = Qubit('01010')
    d = Density([q1, 0.6], [q2, 0.4])

    t = Tr(d)
    assert t.doit() == 1

    # extreme bits
    t = Tr(d, 0)
    assert t.doit() == (0.4 * Density([Qubit('0101'), 1]) +
                        0.6 * Density([Qubit('1011'), 1]))
    t = Tr(d, 4)
    assert t.doit() == (0.4 * Density([Qubit('1010'), 1]) +
                        0.6 * Density([Qubit('0110'), 1]))
    # index somewhere in between
    t = Tr(d, 2)
    assert t.doit() == (0.4 * Density([Qubit('0110'), 1]) +
                        0.6 * Density([Qubit('1010'), 1]))
    #trace all indices
    t = Tr(d, [0, 1, 2, 3, 4])
    assert t.doit() == 1

    # trace some indices, initialized in
    # non-canonical order
    t = Tr(d, [2, 1, 3])
    assert t.doit() == (0.4 * Density([Qubit('00'), 1]) +
                        0.6 * Density([Qubit('10'), 1]))

    # mixed states
    q = (1 / sqrt(2)) * (Qubit('00') + Qubit('11'))
    d = Density([q, 1.0])
    t = Tr(d, 0)
    assert t.doit() == (0.5 * Density([Qubit('0'), 1]) +
                        0.5 * Density([Qubit('1'), 1]))
Пример #4
0
def qapply(e, **options):
    """Apply operators to states in a quantum expression.

    Parameters
    ==========

    e : Expr
        The expression containing operators and states. This expression tree
        will be walked to find operators acting on states symbolically.
    options : dict
        A dict of key/value pairs that determine how the operator actions
        are carried out.

        The following options are valid:

        * ``dagger``: try to apply Dagger operators to the left
          (default: False).
        * ``ip_doit``: call ``.doit()`` in inner products when they are
          encountered (default: True).

    Returns
    =======

    e : Expr
        The original expression, but with the operators applied to states.

    Examples
    ========

        >>> from sympy.physics.quantum import qapply, Ket, Bra
        >>> b = Bra('b')
        >>> k = Ket('k')
        >>> A = k * b
        >>> A
        |k><b|
        >>> qapply(A * b.dual / (b * b.dual))
        |k>
        >>> qapply(k.dual * A / (k.dual * k), dagger=True)
        <b|
        >>> qapply(k.dual * A / (k.dual * k))
        <k|*|k><b|/<k|k>
    """
    from sympy.physics.quantum.density import Density

    dagger = options.get('dagger', False)

    if e == 0:
        return S.Zero

    # This may be a bit aggressive but ensures that everything gets expanded
    # to its simplest form before trying to apply operators. This includes
    # things like (A+B+C)*|a> and A*(|a>+|b>) and all Commutators and
    # TensorProducts. The only problem with this is that if we can't apply
    # all the Operators, we have just expanded everything.
    # TODO: don't expand the scalars in front of each Mul.
    e = e.expand(commutator=True, tensorproduct=True)

    # If we just have a raw ket, return it.
    if isinstance(e, KetBase):
        return e

    # We have an Add(a, b, c, ...) and compute
    # Add(qapply(a), qapply(b), ...)
    elif isinstance(e, Add):
        result = 0
        for arg in e.args:
            result += qapply(arg, **options)
        return result.expand()

    # For a Density operator call qapply on its state
    elif isinstance(e, Density):
        new_args = [(qapply(state, **options), prob)
                    for (state, prob) in e.args]
        return Density(*new_args)

    # For a raw TensorProduct, call qapply on its args.
    elif isinstance(e, TensorProduct):
        return TensorProduct(*[qapply(t, **options) for t in e.args])

    # For a Pow, call qapply on its base.
    elif isinstance(e, Pow):
        return qapply(e.base, **options)**e.exp

    # We have a Mul where there might be actual operators to apply to kets.
    elif isinstance(e, Mul):
        c_part, nc_part = e.args_cnc()
        c_mul = Mul(*c_part)
        nc_mul = Mul(*nc_part)
        if isinstance(nc_mul, Mul):
            result = c_mul * qapply_Mul(nc_mul, **options)
        else:
            result = c_mul * qapply(nc_mul, **options)
        if result == e and dagger:
            return Dagger(qapply_Mul(Dagger(e), **options))
        else:
            return result

    # In all other cases (State, Operator, Pow, Commutator, InnerProduct,
    # OuterProduct) we won't ever have operators to apply to kets.
    else:
        return e
Пример #5
0
def test_doit():

    x, y = symbols("x y")
    A, B, C, D, E, F = symbols("A B C D E F", commutative=False)
    d = Density([XKet(), 0.5], [PxKet(), 0.5])
    assert (0.5 * (PxKet() * Dagger(PxKet())) + 0.5 *
            (XKet() * Dagger(XKet()))) == d.doit()

    # check for kets with expr in them
    d_with_sym = Density([XKet(x * y), 0.5], [PxKet(x * y), 0.5])
    assert (0.5 * (PxKet(x * y) * Dagger(PxKet(x * y))) + 0.5 *
            (XKet(x * y) * Dagger(XKet(x * y)))) == d_with_sym.doit()

    d = Density([(A + B) * C, 1.0])
    assert d.doit() == (1.0 * A * C * Dagger(C) * Dagger(A) +
                        1.0 * A * C * Dagger(C) * Dagger(B) +
                        1.0 * B * C * Dagger(C) * Dagger(A) +
                        1.0 * B * C * Dagger(C) * Dagger(B))

    #  With TensorProducts as args
    # Density with simple tensor products as args
    t = TensorProduct(A, B, C)
    d = Density([t, 1.0])
    assert d.doit() == 1.0 * TensorProduct(A * Dagger(A), B * Dagger(B),
                                           C * Dagger(C))

    # Density with multiple Tensorproducts as states
    t2 = TensorProduct(A, B)
    t3 = TensorProduct(C, D)

    d = Density([t2, 0.5], [t3, 0.5])
    assert d.doit() == (0.5 * TensorProduct(A * Dagger(A), B * Dagger(B)) +
                        0.5 * TensorProduct(C * Dagger(C), D * Dagger(D)))

    # Density with mixed states
    d = Density([t2 + t3, 1.0])
    assert d.doit() == (1.0 * TensorProduct(A * Dagger(A), B * Dagger(B)) +
                        1.0 * TensorProduct(A * Dagger(C), B * Dagger(D)) +
                        1.0 * TensorProduct(C * Dagger(A), D * Dagger(B)) +
                        1.0 * TensorProduct(C * Dagger(C), D * Dagger(D)))

    # Density operators with spin states
    tp1 = TensorProduct(JzKet(1, 1), JzKet(1, -1))
    d = Density([tp1, 1])

    # full trace
    t = Tr(d)
    assert t.doit() == 1

    # Partial trace on density operators with spin states
    t = Tr(d, [0])
    assert t.doit() == JzKet(1, -1) * Dagger(JzKet(1, -1))
    t = Tr(d, [1])
    assert t.doit() == JzKet(1, 1) * Dagger(JzKet(1, 1))

    # with another spin state
    tp2 = TensorProduct(JzKet(S.Half, S.Half), JzKet(S.Half, Rational(-1, 2)))
    d = Density([tp2, 1])

    # full trace
    t = Tr(d)
    assert t.doit() == 1

    # Partial trace on density operators with spin states
    t = Tr(d, [0])
    assert t.doit() == JzKet(S.Half, Rational(-1, 2)) * Dagger(
        JzKet(S.Half, Rational(-1, 2)))
    t = Tr(d, [1])
    assert t.doit() == JzKet(S.Half, S.Half) * Dagger(JzKet(S.Half, S.Half))
Пример #6
0
def test_fidelity():
    # test with kets
    up = JzKet(S.Half, S.Half)
    down = JzKet(S.Half, Rational(-1, 2))
    updown = (S.One / sqrt(2)) * up + (S.One / sqrt(2)) * down

    # check with matrices
    up_dm = represent(up * Dagger(up))
    down_dm = represent(down * Dagger(down))
    updown_dm = represent(updown * Dagger(updown))

    assert abs(fidelity(up_dm, up_dm) - 1) < 1e-3
    assert fidelity(up_dm, down_dm) < 1e-3
    assert abs(fidelity(up_dm, updown_dm) - (S.One / sqrt(2))) < 1e-3
    assert abs(fidelity(updown_dm, down_dm) - (S.One / sqrt(2))) < 1e-3

    # check with density
    up_dm = Density([up, 1.0])
    down_dm = Density([down, 1.0])
    updown_dm = Density([updown, 1.0])

    assert abs(fidelity(up_dm, up_dm) - 1) < 1e-3
    assert abs(fidelity(up_dm, down_dm)) < 1e-3
    assert abs(fidelity(up_dm, updown_dm) - (S.One / sqrt(2))) < 1e-3
    assert abs(fidelity(updown_dm, down_dm) - (S.One / sqrt(2))) < 1e-3

    # check mixed states with density
    updown2 = sqrt(3) / 2 * up + S.Half * down
    d1 = Density([updown, 0.25], [updown2, 0.75])
    d2 = Density([updown, 0.75], [updown2, 0.25])
    assert abs(fidelity(d1, d2) - 0.991) < 1e-3
    assert abs(fidelity(d2, d1) - fidelity(d1, d2)) < 1e-3

    # using qubits/density(pure states)
    state1 = Qubit("0")
    state2 = Qubit("1")
    state3 = S.One / sqrt(2) * state1 + S.One / sqrt(2) * state2
    state4 = sqrt(Rational(2, 3)) * state1 + S.One / sqrt(3) * state2

    state1_dm = Density([state1, 1])
    state2_dm = Density([state2, 1])
    state3_dm = Density([state3, 1])

    assert fidelity(state1_dm, state1_dm) == 1
    assert fidelity(state1_dm, state2_dm) == 0
    assert abs(fidelity(state1_dm, state3_dm) - 1 / sqrt(2)) < 1e-3
    assert abs(fidelity(state3_dm, state2_dm) - 1 / sqrt(2)) < 1e-3

    # using qubits/density(mixed states)
    d1 = Density([state3, 0.70], [state4, 0.30])
    d2 = Density([state3, 0.20], [state4, 0.80])
    assert abs(fidelity(d1, d1) - 1) < 1e-3
    assert abs(fidelity(d1, d2) - 0.996) < 1e-3
    assert abs(fidelity(d1, d2) - fidelity(d2, d1)) < 1e-3

    # TODO: test for invalid arguments
    # non-square matrix
    mat1 = [[0, 0], [0, 0], [0, 0]]

    mat2 = [[0, 0], [0, 0]]
    raises(ValueError, lambda: fidelity(mat1, mat2))

    # unequal dimensions
    mat1 = [[0, 0], [0, 0]]
    mat2 = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
    raises(ValueError, lambda: fidelity(mat1, mat2))

    # unsupported data-type
    x, y = 1, 2  # random values that is not a matrix
    raises(ValueError, lambda: fidelity(x, y))
Пример #7
0
def test_get_prob():
    x, y = symbols("x y")
    d = Density([Ket(0), x], [Ket(1), y])
    probs = (d.get_prob(0), d.get_prob(1))
    assert probs[0] == x and probs[1] == y
Пример #8
0
def test_get_state():
    x, y = symbols("x y")
    d = Density([Ket(0), x], [Ket(1), y])
    states = (d.get_state(0), d.get_state(1))
    assert states[0] == Ket(0) and states[1] == Ket(1)
Пример #9
0
def test_states():
    d = Density([Ket(0), 0.5], [Ket(1), 0.5])
    states = d.states()
    assert states[0] == Ket(0) and states[1] == Ket(1)