Exemplo n.º 1
0
#!/usr/bin/env python3

# FILE CONTENTS: (symbolic) methods for performing qubit operations

import sympy as sym
from itertools import product as cartesian_product
from itertools import combinations, permutations
from sympy.physics.quantum import TensorProduct as tensor

# single-atom pseudospin states
dn = sym.Matrix([1, 0])
up = sym.Matrix([0, 1])

# two-atom pseudospin states
uu = tensor(up, up)
ud = tensor(up, dn)
du = tensor(dn, up)
dd = tensor(dn, dn)


# all states of n qubits
def qubit_states(n):
    return cartesian_product([-1, 1], repeat=n)


# single-qubit matrix entry: | final >< initial |
def qubit_matrix_entry(initial, final):
    state_in = (up if initial == 1 else dn)
    state_out = (up if final == 1 else dn)
    return tensor(state_out, state_in.H)
Exemplo n.º 2
0
def qubit_matrix_entry(initial, final):
    state_in = (up if initial == 1 else dn)
    state_out = (up if final == 1 else dn)
    return tensor(state_out, state_in.H)
Exemplo n.º 3
0
    def elem(self, atom_number=None, debug=False):
        assert (len(self.vec) % 2 == 0)
        if atom_number == None: atom_number = len(self.vec) // 2
        vec = deepcopy(self.vec)

        sign = 1
        current_spin = [0 for n in range(atom_number)]
        current_band = [0 for n in range(atom_number)]
        zero_matrix = sym.zeros(2**atom_number)
        while len(vec) > 0:

            if vec[0].create: return zero_matrix

            if vec[0].band != current_band[vec[0].nuclear_spin]:
                return zero_matrix

            if (current_spin[vec[0].nuclear_spin] != 0
                    and vec[0].spin != current_spin[vec[0].nuclear_spin]):
                return zero_matrix

            found = False  # have we found a matching fermionic operator?
            for ii in range(1, len(vec)):

                match = vec[0].nuclear_spin == vec[ii].nuclear_spin

                if match:
                    if not vec[ii].create: return zero_matrix

                    found = True
                    if debug:
                        print()
                        print(vec[0])
                        print(vec[ii])
                        print(vec[::-1])
                    current_spin[vec[0].nuclear_spin] = vec[ii].spin
                    current_band[vec[0].nuclear_spin] = vec[ii].band
                    vec.pop(ii)
                    vec.pop(0)
                    break

                else:
                    sign *= -1

            if not found: return zero_matrix

        if (0 in current_spin
                or current_band != [0 for n in range(atom_number)]):
            return zero_matrix

        if debug:
            print()
            print(self)

        # individual effective spin operators
        spin_ops = [sym.eye(2) for n in range(atom_number)]
        for nuclear_spin in set(
            [operator.nuclear_spin for operator in self.vec]):
            # loop over annihilation operators
            for operator in self.vec:
                if operator.nuclear_spin == nuclear_spin:
                    s_in = operator.spin
                    break
            # loop over creation operators
            for operator in self.vec[::-1]:
                if operator.nuclear_spin == nuclear_spin:
                    s_out = operator.spin
                    break

            if debug:
                print()
                print(nuclear_spin)
                print(s_in, "-->", s_out)

            spin_ops[nuclear_spin] = qubit_matrix_entry(s_in, s_out)

        if debug:
            print()
            print("sign:", sign)
            pprint(spin_ops)

        return sign * tensor(*spin_ops)
Exemplo n.º 4
0
def convert_to_sympy_matrix(expr, full_space=None):
    """Convert a QAlgebra expression to an explicit ``n x n`` instance of
    `sympy.Matrix`, where ``n`` is the dimension of `full_space`. The entries
    of the matrix may contain symbols.

    Parameters:
        expr: a QAlgebra expression
        full_space (HilbertSpace): The
            Hilbert space in which `expr` is defined. If not given,
            ``expr.space`` is used. The Hilbert space must have a well-defined
            basis.

    Raises:
        BasisNotSetError: if `full_space` does not have a defined basis
        ValueError: if `expr` is not in `full_space`, or if `expr` cannot be
            converted.
    """
    if full_space is None:
        full_space = expr.space
    if not expr.space.is_tensor_factor_of(full_space):
        raise ValueError("expr must be in full_space")
    if expr is IdentityOperator:
        return sympy.eye(full_space.dimension)
    elif expr is ZeroOperator:
        return 0
    elif isinstance(expr, LocalOperator):
        n = full_space.dimension
        if full_space != expr.space:
            all_spaces = full_space.local_factors
            own_space_index = all_spaces.index(expr.space)
            factors = [
                sympy.eye(s.dimension) for s in all_spaces[:own_space_index]
            ]
            factors.append(convert_to_sympy_matrix(expr, expr.space))
            factors.extend(
                [
                    sympy.eye(s.dimension)
                    for s in all_spaces[own_space_index + 1 :]
                ]
            )
            return tensor(*factors)
        if isinstance(expr, (Create, Jz, Jplus)):
            return SympyCreate(n)
        elif isinstance(expr, (Destroy, Jminus)):
            return SympyCreate(n).H
        elif isinstance(expr, Phase):
            phi = expr.phase
            result = sympy.zeros(n)
            for i in range(n):
                result[i, i] = sympy.exp(sympy.I * i * phi)
            return result
        elif isinstance(expr, Displace):
            alpha = expr.operands[1]
            a = SympyCreate(n)
            return (alpha * a - alpha.conjugate() * a.H).exp()
        elif isinstance(expr, Squeeze):
            eta = expr.operands[1]
            a = SympyCreate(n)
            return (
                (eta / 2) * a ** 2 - (eta.conjugate() / 2) * (a.H) ** 2
            ).exp()
        elif isinstance(expr, LocalSigma):
            ket = basis_state(expr.index_j, n)
            bra = basis_state(expr.index_k, n).H
            return ket * bra
        else:
            raise ValueError(
                "Cannot convert '%s' of type %s" % (str(expr), type(expr))
            )
    elif isinstance(expr, Operator) and isinstance(expr, Operation):
        if isinstance(expr, OperatorPlus):
            s = convert_to_sympy_matrix(expr.operands[0], full_space)
            for op in expr.operands[1:]:
                s += convert_to_sympy_matrix(op, full_space)
            return s
        elif isinstance(expr, OperatorTimes):
            # if any factor acts non-locally, we need to expand distributively.
            if any(len(op.space) > 1 for op in expr.operands):
                se = expr.expand()
                if se == expr:
                    raise ValueError(
                        "Cannot represent as sympy matrix: %s" % expr
                    )
                return convert_to_sympy_matrix(se, full_space)
            all_spaces = full_space.local_factors
            by_space = []
            ck = 0
            for ls in all_spaces:
                # group factors by associated local space
                ls_ops = [
                    convert_to_sympy_matrix(o, o.space)
                    for o in expr.operands
                    if o.space == ls
                ]
                if len(ls_ops):
                    # compute factor associated with local space
                    by_space.append(ls_ops[0])
                    for ls_op in ls_ops[1:]:
                        by_space[-1] *= ls_op
                    ck += len(ls_ops)
                else:
                    # if trivial action, take identity matrix
                    by_space.append(sympy.eye(ls.dimension))
            assert ck == len(expr.operands)
            # combine local factors in tensor product
            if len(by_space) == 1:
                return by_space[0]
            else:
                return tensor(*by_space)
        elif isinstance(expr, Adjoint):
            return convert_to_sympy_matrix(expr.operand, full_space).H
        elif isinstance(expr, PseudoInverse):
            raise NotImplementedError(
                'Cannot convert PseudoInverse to sympy matrix'
            )
        elif isinstance(expr, NullSpaceProjector):
            raise NotImplementedError(
                'Cannot convert NullSpaceProjector to sympy'
            )
        elif isinstance(expr, ScalarTimesOperator):
            return expr.coeff * convert_to_sympy_matrix(expr.term, full_space)
        else:
            raise ValueError(
                "Cannot convert '%s' of type %s" % (str(expr), type(expr))
            )
    else:
        raise ValueError(
            "Cannot convert '%s' of type %s" % (str(expr), type(expr))
        )
Exemplo n.º 5
0
import sys
import time

I = np.array([[1., 0.], [0., 1.]])
zero = np.array([[1., 0.], [0., 0.]])
one = np.array([[0., 0.], [0., 1.]])
X = np.array([[0., 1.], [1., 0.]])

I_2 = np.eye(4)
I_3 = np.eye(8)
I_4 = np.eye(16)
I_5 = np.eye(32)
I_6 = np.eye(64)

# T1 conditional on 1,1 - acts on qubits 1,2 and flips 8
U_T11 = tensor(zero, tensor(zero, I_6)) + tensor(zero, tensor(
    one, I_6)) + tensor(one, tensor(zero, I_6)) + tensor(
        one, tensor(one, tensor(I_5, X)))

# T2 conditional on 1,0 - acts on qubits 1,2 and flips 8
U_T21 = tensor(zero, tensor(zero, I_6)) + tensor(zero, tensor(
    one, I_6)) + tensor(one, tensor(zero, tensor(I_5, X))) + tensor(
        one, tensor(one, I_6))
# T3 conditional on 0,1 - acts on qubits 1,2 and flips 8
U_T31 = tensor(zero, tensor(
    zero, I_6)) + tensor(zero, tensor(one, tensor(I_5, X))) + tensor(
        one, tensor(zero, I_6)) + tensor(one, tensor(one, tensor(I_5, X)))
# T4 conditional on 0,0 - acts on qubits 1,2 and flips 8
U_T41 = tensor(zero, tensor(zero, tensor(I_5, X))) + tensor(
    zero, tensor(one, I_6)) + tensor(one, tensor(zero, I_6)) + tensor(
        one, tensor(one, I_6))
Exemplo n.º 6
0
        -1j * cos / (1 - sin), sin / (1 - cos), -sin / (1 - cos)
    ]
    #  z[3], z[4], z[5], = z[5], z[3], z[4]
    c = 1
    if np.sum(i) == 0:
        for a1 in range(12):
            for b1 in range(a1 + 1, 12):
                c = c * (z[a1] - z[b1])**(i[a1] * i[b1] / 2)
        return c
    else:
        return 0


Gs4 = Qobj(np.zeros((16, 1)), [Lis(2, 4), Lis(1, 4)])
for i1, i2, i3, i4 in itr.product([-1, 1], [-1, 1], [-1, 1], [-1, 1]):
    Gs42 = Gs4 + Semion4([i1, i2, i3, i4]) * tensor(v(i1), v(i2), v(i3), v(i4))
    Gs4 = Gs42
NGs4 = Gs4 / np.linalg.norm(Gs4)

Gs6 = Qobj(np.zeros((64, 1)), [Lis(2, 6), Lis(1, 6)])
for i1, i2, i3, i4, i5, i6 in itr.product([-1, 1], [-1, 1], [-1, 1], [-1, 1],
                                          [-1, 1], [-1, 1]):
    Gs62 = Gs6 + Semion6([i1, i2, i3, i4, i5, i6]) * tensor(
        v(i1), v(i2), v(i3), v(i4), v(i5), v(i6))
    Gs6 = Gs62
NGs6 = Gs6 / np.linalg.norm(Gs6)

Gs8 = Qobj(np.zeros((2**8, 1)), [Lis(2, 8), Lis(1, 8)])
for i1, i2, i3, i4, i5, i6, i7, i8 in itr.product([-1, 1], [-1, 1], [-1, 1],
                                                  [-1, 1], [-1, 1], [-1, 1],
                                                  [-1, 1], [-1, 1]):
Exemplo n.º 7
0
def convert_to_sympy_matrix(expr, full_space=None):
    """Convert a QNET expression to an explicit ``n x n`` instance of
    `sympy.Matrix`, where ``n`` is the dimension of `full_space`. The entries
    of the matrix may contain symbols.

    Parameters:
        expr: a QNET expression
        full_space (qnet.algebra.hilbert_space_algebra.HilbertSpace): The
            Hilbert space in which `expr` is defined. If not given,
            ``expr.space`` is used. The Hilbert space must have a well-defined
            basis.

    Raises:
        qnet.algebra.hilbert_space_algebra.BasisNotSetError: if `full_space`
            does not have a defined basis
        ValueError: if `expr` is not in `full_space`, or if `expr` cannot be
            converted.
    """
    if full_space is None:
        full_space = expr.space
    if not expr.space.is_tensor_factor_of(full_space):
        raise ValueError("expr must be in full_space")
    if expr is IdentityOperator:
        return sympy.eye(full_space.dimension)
    elif expr is ZeroOperator:
        return 0
    elif isinstance(expr, LocalOperator):
        n = full_space.dimension
        if full_space != expr.space:
            all_spaces = full_space.local_factors()
            own_space_index = all_spaces.index(expr.space)
            return tensor(*( [sympy.eye(s.dimension)
                              for s in all_spaces[:own_space_index]]
                           + convert_to_sympy_matrix(expr, expr.space)
                           + [sympy.eye(s.dimension)
                              for s in all_spaces[own_space_index + 1:]]
                         ))
        if isinstance(expr, (Create, Jz, Jplus)):
            return SympyCreate(n)
        elif isinstance(expr, (Destroy, Jminus)):
            return SympyCreate(n).H
        elif isinstance(expr, Phase):
            phi = expr.operands[1]
            result = sympy.zeros(n)
            for i in range(n):
                result[i,i] = sympy.exp(sympy.I * i * phi)
            return result
        elif isinstance(expr, Displace):
            alpha = expr.operands[1]
            a = SympyCreate(n)
            return  (alpha * a - alpha.conjugate() * a.H).exp()
        elif isinstance(expr, Squeeze):
            eta = expr.operands[1]
            a = SympyCreate(n)
            return ((eta/2) * a**2 - (eta.conjugate()/2) * (a.H)**2).exp()
        elif isinstance(expr, LocalSigma):
            k, j = expr.operands[1:]
            ket = basis_state(k, n)
            bra = basis_state(j, n).H
            return ket * bra
        else:
            raise ValueError("Cannot convert '%s' of type %s"
                             % (str(expr), type(expr)))
    elif isinstance(expr, OperatorOperation):
        if isinstance(expr, OperatorPlus):
            s = convert_to_sympy_matrix(expr.operands[0], full_space)
            for op in expr.operands[1:]:
                s += convert_to_sympy_matrix(op, full_space)
            return s
        elif isinstance(expr, OperatorTimes):
            # if any factor acts non-locally, we need to expand distributively.
            if any(len(op.space) > 1 for op in expr.operands):
                se = expr.expand()
                if se == expr:
                    raise ValueError("Cannot represent as sympy matrix: %s"
                                     % expr)
                return convert_to_sympy_matrix(se, full_space)
            all_spaces = full_space.local_factors()
            by_space = []
            ck = 0
            for ls in all_spaces:
                # group factors by associated local space
                ls_ops = [convert_to_sympy_matrix(o, o.space)
                          for o in expr.operands if o.space == ls]
                if len(ls_ops):
                    # compute factor associated with local space
                    by_space.append(ls_ops[0])
                    for ls_op in ls_ops[1:]:
                        by_space[-1] *= ls_op
                    ck += len(ls_ops)
                else:
                    # if trivial action, take identity matrix
                    by_space.append(sympy.eye(ls.dimension))
            assert ck == len(expr.operands)
            # combine local factors in tensor product
            if len(by_space) == 1:
                return by_space[0]
            else:
                return tensor(*by_space)
        elif isinstance(expr, Adjoint):
            return convert_to_sympy_matrix(expr.operand, full_space).H
        elif isinstance(expr, PseudoInverse):
            raise NotImplementedError('Cannot convert PseudoInverse to sympy '
                    'matrix')
        elif isinstance(expr, NullSpaceProjector):
            raise NotImplementedError('Cannot convert NullSpaceProjector to '
                    'sympy')
        else:
            raise ValueError("Cannot convert '%s' of type %s"
                             % (str(expr), type(expr)))
    elif isinstance(expr, ScalarTimesOperator):
        return expr.coeff * convert_to_sympy_matrix(expr.term, full_space)
    elif isinstance(expr, ScalarTimesOperator):
        raise NotImplementedError('Cannot convert OperatorTrace to '
                'sympy')
        # actually, this is perfectly doable in principle, but requires a bit
        # of work
    else:
        raise ValueError("Cannot convert '%s' of type %s"
                         % (str(expr), type(expr)))