Ejemplo n.º 1
0
 def test_wrong_term_length(self):
     """Test exception raised for wrong terms"""
     with pytest.raises(BoseHubbardError):
         H = bose_hubbard(2, 2, 1, 0.1, 0.2)
         H -= BosonOperator('5^ 5 5^')
         H += BosonOperator('5^ 5')
         extract_onsite_chemical(H)
Ejemplo n.º 2
0
def squeezing(r, phi=0, mode=0, hbar=2):
    r"""Returns the Hamiltonian of the squeezing operation.

    The time evolution unitary associated with squeezing is

    .. math::
        S(r,\phi) = \exp\left(\frac{r}{2}\left(e^{-i\phi}\a^2 -e^{i\phi}{\ad}^{2} \right) \right)

    Therefore, :math:`U=e^{-iHt/\hbar}` where
    :math:`H =  \frac{i\hbar}{2}\left(e^{-i\phi}\a^2 -e^{i\phi}{\ad}^{2}\right)` and :math:`t=r`.

    Args:
        r (float): the squeezing magnitude
        phi (float): the quadrature angle in which the squeezing occurs.
            :math:`\phi=0` corresponds to squeezing in the :math:`\x` quadrature,
            and :math:`\phi=\pi/2` corresponds to squeezing in the
            :math:`\p` quadrature.
        mode (int): the qumode on which the operation acts
        hbar (float): the scaling convention chosen in the definition of the quadrature
            operators: :math:`[\x,\p]=i\hbar`
    Returns:
        tuple (BosonOperator, t): tuple containing the Hamiltonian
        representing the operation and the propagation time
    """
    H = BosonOperator('{} {}'.format(mode, mode), np.exp(-1j * phi))
    H -= BosonOperator('{}^ {}^'.format(mode, mode), np.exp(1j * phi))
    return (1j / 2) * H * hbar, r
Ejemplo n.º 3
0
def beamsplitter(theta=np.pi / 4, phi=0, mode1=0, mode2=1, hbar=2):
    r"""Returns the Hamiltonian of the beamsplitter operation.

    The time evolution unitary associated with the beamsplitter is

    .. math::
        B(\theta,\phi) = \exp\left(\theta (e^{i \phi} \ad_0 \a_1
             - e^{-i \phi}\a_0 \ad_1) \right)

    Therefore, :math:`U=e^{-iHt/\hbar}` where
    :math:`H(\phi) = {i}{\hbar}\left(e^{i \phi} \ad_0 \a_1 - e^{-i \phi}\a_0 \ad_1\right)`
    and :math:`t=\theta`.

    Args:
        theta (float): transmitivity angle :math:`\theta` where :math:`t=\cos(\theta)`
        phi (float): phase angle :math:`\phi` where :math:`r=e^{i\phi}\sin(\theta)`
        mode1 (int): the first qumode :math:`\a_0` on which the operation acts
        mode2 (int): the second qumode :math:`\a_1` on which the operation acts
        hbar (float): the scaling convention chosen in the definition of the quadrature
            operators: :math:`[\x,\p]=i\hbar`
    Returns:
        tuple (BosonOperator, t): tuple containing the Hamiltonian
        representing the operation and the propagation time
    """
    H = BosonOperator('{}^ {}'.format(mode1, mode2),
                      np.exp(1j * (np.pi - phi)))
    H += BosonOperator('{} {}^'.format(mode1, mode2),
                       -np.exp(-1j * (np.pi - phi)))
    return 1j * H * hbar, theta
Ejemplo n.º 4
0
 def test_two_mode(self):
     q = QuadOperator('p2 q0')
     b = get_boson_operator(q, hbar=self.hbar)
     expected = -1j*self.hbar/2 \
         * (BosonOperator('0') + BosonOperator('0^')) \
         * (BosonOperator('2') - BosonOperator('2^'))
     self.assertTrue(b == expected)
Ejemplo n.º 5
0
 def test_p_squared(self):
     b = self.hbar * (-BosonOperator('1^ 1^') - BosonOperator('1 1') +
                      BosonOperator('') + 2 * BosonOperator('1^ 1')) / 2
     q = normal_ordered(get_quad_operator(b, hbar=self.hbar),
                        hbar=self.hbar)
     expected = QuadOperator('p1 p1')
     self.assertTrue(q == expected)
Ejemplo n.º 6
0
 def test_coefficients_differ(self):
     """Test exception raised for differing coefficients"""
     self.logTestName()
     with self.assertRaises(BoseHubbardError):
         H = BosonOperator('0^ 0 1^ 1', 0.5)
         H += BosonOperator('0^ 0 2^ 2', 1)
         extract_dipole(H)
Ejemplo n.º 7
0
 def test_complex_tunneling_coefficient(self):
     """Test exception raised if the tunelling coefficient is complex"""
     self.logTestName()
     with self.assertRaises(BoseHubbardError):
         H = BosonOperator('0 1^', 1+2j)
         H += BosonOperator('0^ 1', 1+2j)
         extract_tunneling(H)
Ejemplo n.º 8
0
 def test_ladder_wrong_form(self):
     """Test exception raised for wrong ladder operators"""
     with self.assertRaises(BoseHubbardError):
         H = bose_hubbard(2, 2, 1, 0)
         H -= BosonOperator('5^ 6^')
         H -= BosonOperator('6 5')
         extract_tunneling(H)
Ejemplo n.º 9
0
def two_mode_squeezing(r, phi=0, mode1=0, mode2=1, hbar=2):
    r"""Returns the Hamiltonian of the two-mode squeezing operation.

    The time evolution unitary associated with two-mode squeezing is

    .. math::
        S_2(r,\phi) = \exp\left(r\left(e^{-i\phi}\a_0 \a_1 -e^{i\phi}{\ad_0} \ad_1 \right) \right)

    Therefore, :math:`U=e^{-iHt/\hbar}` where
    :math:`H = {i}{\hbar}\left(e^{-i\phi}\a_0 \a_1 -e^{i\phi}{\ad_0} \ad_1\right)` and :math:`t=r`.

    Args:
        r (float): the squeezing magnitude
        phi (float): the quadrature in which the squeezing occurs.
            :math:`\phi=0` corresponds to squeezing in the :math:`\x` quadrature,
            and :math:`\phi=\pi/2` corresponds to squeezing in the
            :math:`\p` quadrature.
        mode1 (int): the first qumode :math:`\a_0` on which the operation acts
        mode2 (int): the second qumode :math:`\a_1` on which the operation acts
        hbar (float): the scaling convention chosen in the definition of the quadrature
            operators: :math:`[\x,\p]=i\hbar`
    Returns:
        tuple (BosonOperator, t): tuple containing the Hamiltonian
        representing the operation and the propagation time
    """
    H = BosonOperator('{} {}'.format(mode1, mode2),
                      np.exp(-1j * (np.pi + phi)))
    H -= BosonOperator('{}^ {}^'.format(mode1, mode2),
                       np.exp(1j * (np.pi + phi)))
    return 1j * H * hbar, r
Ejemplo n.º 10
0
def displacement(alpha, mode=0, hbar=2):
    r"""Returns the Hamiltonian of the displacement operation.

    The time evolution unitary associated with displacement is

    .. math::
        D(\alpha) = \exp( \alpha \ad -\alpha^* \a) = \exp(r (e^{i\phi}\ad -e^{-i\phi}\a))

    where :math:`\alpha=r e^{i \phi}` with :math:`r \geq 0` and :math:`\phi \in [0,2 \pi)`.

    Therefore, :math:`U=e^{-iHt/\hbar}` where
    :math:`H = {i}{\hbar}(e^{i\phi}\ad -e^{-i\phi}\a)` and :math:`t=r`.

    Args:
        a (complex): the displacement in the phase space
        mode (int): the qumode on which the operation acts
        hbar (float): the scaling convention chosen in the definition of the quadrature
            operators: :math:`[\x,\p]=i\hbar`
    Returns:
        tuple (BosonOperator, t): tuple containing the Hamiltonian
        representing the operation and the propagation time
    """
    if alpha == 0.:
        return BosonOperator(''), 0

    r = np.abs(alpha)
    phi = np.angle(alpha)
    H = BosonOperator('{}^'.format(mode), np.exp(1j * phi))
    H -= BosonOperator('{}'.format(mode), np.exp(-1j * phi))
    return 1j * H * hbar, r
Ejemplo n.º 11
0
 def test_differing_onsite(self):
     """Test exception raised for differing coefficients"""
     with pytest.raises(BoseHubbardError):
         H = bose_hubbard(2, 2, 1, 0.1, 0.2)
         H -= BosonOperator('5^ 5 5^ 5')
         H += BosonOperator('5^ 5')
         extract_onsite_chemical(H)
Ejemplo n.º 12
0
 def test_incorrect_ladders(self):
     """Test exception raised for wrong ladder operators"""
     with pytest.raises(BoseHubbardError):
         H = bose_hubbard(2, 2, 1, 0.1, 0.2)
         H -= BosonOperator('5^ 5^ 5^ 5^')
         H -= BosonOperator('5 5^ 5 5^')
         extract_onsite_chemical(H)
Ejemplo n.º 13
0
def get_boson_operator(operator, hbar=1.):
    """Convert to BosonOperator.

    Args:
        operator: QuadOperator.
        hbar (float): the value of hbar used in the definition
            of the commutator [q_i, p_j] = i hbar delta_ij.
            By default hbar=1.

    Returns:
        boson_operator: An instance of the BosonOperator class.
    """
    boson_operator = BosonOperator()

    if isinstance(operator, QuadOperator):
        for term, coefficient in operator.terms.items():
            tmp = BosonOperator('', coefficient)
            for i, d in term:
                if d == 'q':
                    coeff = numpy.sqrt(hbar / 2)
                    sign = 1
                elif d == 'p':
                    coeff = -1j * numpy.sqrt(hbar / 2)
                    sign = -1

                tmp *= coeff * (BosonOperator(((i, 0))) + BosonOperator(
                    ((i, 1)), sign))
            boson_operator += tmp

    else:
        raise TypeError("Only QuadOperator is currently "
                        "supported for get_boson_operator.")

    return boson_operator
Ejemplo n.º 14
0
 def test_ladder_wrong_form(self):
     """Test exception raised for wrong ladder operators"""
     with pytest.raises(BoseHubbardError):
         H = bose_hubbard(2, 2, 1, 1, 1, 0.5)
         H += BosonOperator('5^ 5 6^ 6^')
         H -= BosonOperator('6 5')
         extract_dipole(H)
Ejemplo n.º 15
0
 def test_q_squared(self):
     b = self.hbar * (BosonOperator('0^ 0^') + BosonOperator('0 0') +
                      BosonOperator('') + 2 * BosonOperator('0^ 0')) / 2
     q = normal_ordered(get_quad_operator(b, hbar=self.hbar),
                        hbar=self.hbar)
     expected = QuadOperator('q0 q0')
     self.assertTrue(q == expected)
Ejemplo n.º 16
0
def load_operator(file_name=None, data_directory=None, plain_text=False):
    """Load FermionOperator or QubitOperator from file.

    Args:
        file_name: The name of the saved file.
        data_directory: Optional data directory to change from default data
                        directory specified in config file.
        plain_text: Whether the input file is plain text

    Returns:
        operator: The stored FermionOperator, BosonOperator,
            QuadOperator, or QubitOperator

    Raises:
        TypeError: Operator of invalid type.
    """
    file_path = get_file_path(file_name, data_directory)

    if plain_text:
        with open(file_path, 'r') as f:
            data = f.read()
            operator_type, operator_terms = data.split(":\n")

        if operator_type == 'FermionOperator':
            operator = FermionOperator(operator_terms)
        elif operator_type == 'BosonOperator':
            operator = BosonOperator(operator_terms)
        elif operator_type == 'QubitOperator':
            operator = QubitOperator(operator_terms)
        elif operator_type == 'QuadOperator':
            operator = QuadOperator(operator_terms)
        else:
            raise TypeError('Operator of invalid type.')
    else:
        with open(file_path, 'rb') as f:
            data = marshal.load(f)
            operator_type = data[0]
            operator_terms = data[1]

        if operator_type == 'FermionOperator':
            operator = FermionOperator()
            for term in operator_terms:
                operator += FermionOperator(term, operator_terms[term])
        elif operator_type == 'BosonOperator':
            operator = BosonOperator()
            for term in operator_terms:
                operator += BosonOperator(term, operator_terms[term])
        elif operator_type == 'QubitOperator':
            operator = QubitOperator()
            for term in operator_terms:
                operator += QubitOperator(term, operator_terms[term])
        elif operator_type == 'QuadOperator':
            operator = QuadOperator()
            for term in operator_terms:
                operator += QuadOperator(term, operator_terms[term])
        else:
            raise TypeError('Operator of invalid type.')

    return operator
Ejemplo n.º 17
0
    def test_commutator_hopping_operators(self):
        com = commutator(3 * FermionOperator('1^ 2'), FermionOperator('2^ 3'))
        com = normal_ordered(com)
        self.assertEqual(com, FermionOperator('1^ 3', 3))

        com = commutator(3 * BosonOperator('1^ 2'), BosonOperator('2^ 3'))
        com = normal_ordered(com)
        self.assertTrue(com == BosonOperator('1^ 3', 3))
Ejemplo n.º 18
0
 def test_boson_form(self):
     """Test bosonic form is correct"""
     H = normal_ordered(get_boson_operator(self.H, hbar=self.hbar))
     expected = BosonOperator('0 1', -1)
     expected += BosonOperator('0 1^', -1)
     expected += BosonOperator('0^ 1', -1)
     expected += BosonOperator('0^ 1^', -1)
     self.assertEqual(H, expected)
Ejemplo n.º 19
0
 def test_boson_form(self, hbar):
     """Test bosonic form is correct"""
     H = normal_ordered(get_boson_operator(self.H, hbar=hbar))
     expected = BosonOperator('0 1', -1)
     expected += BosonOperator('0 1^', -1)
     expected += BosonOperator('0^ 1', -1)
     expected += BosonOperator('0^ 1^', -1)
     assert H == expected
Ejemplo n.º 20
0
    def test_commutes_number_operators(self):
        com = commutator(FermionOperator('4^ 3^ 4 3'), FermionOperator('2^ 2'))
        com = normal_ordered(com)
        self.assertEqual(com, FermionOperator.zero())

        com = commutator(BosonOperator('4^ 3^ 4 3'), BosonOperator('2^ 2'))
        com = normal_ordered(com)
        self.assertTrue(com == BosonOperator.zero())
Ejemplo n.º 21
0
 def test_boson_form(self):
     """Test bosonic form is correct"""
     self.logTestName()
     H = normal_ordered(get_boson_operator(self.H, hbar=self.hbar))
     expected = BosonOperator('0 0', -0.5)
     expected += BosonOperator('0^ 0', -1)
     expected += BosonOperator('0^ 0^', -0.5)
     expected += BosonOperator('', -0.5)
     self.assertEqual(H, expected)
Ejemplo n.º 22
0
 def test_two_term(self):
     b = BosonOperator('0^ 0') + BosonOperator('0 0^')
     q = get_quad_operator(b, hbar=self.hbar)
     expected = (QuadOperator('q0') - 1j*QuadOperator('p0')) \
         * (QuadOperator('q0') + 1j*QuadOperator('p0')) \
         + (QuadOperator('q0') + 1j*QuadOperator('p0')) \
         * (QuadOperator('q0') - 1j*QuadOperator('p0'))
     expected /= 2 * self.hbar
     self.assertTrue(q == expected)
Ejemplo n.º 23
0
    def test_commutes_identity(self):
        com = commutator(FermionOperator.identity(),
                         FermionOperator('2^ 3', 2.3))
        self.assertEqual(com, FermionOperator.zero())

        com = commutator(BosonOperator.identity(), BosonOperator('2^ 3', 2.3))
        self.assertTrue(com == BosonOperator.zero())

        com = commutator(QuadOperator.identity(), QuadOperator('q2 p3', 2.3))
        self.assertTrue(com == QuadOperator.zero())
Ejemplo n.º 24
0
    def test_too_many_terms(self):
        """Test exception raised for wrong number of terms"""
        with pytest.raises(BoseHubbardError):
            H = bose_hubbard(2, 2, 1, 0.1, 0.2)
            H -= BosonOperator('0^ 0^ 0^ 0^')
            extract_onsite_chemical(H)

        with pytest.raises(BoseHubbardError):
            H = bose_hubbard(2, 2, 1, 0.1, 0.2)
            H -= BosonOperator('5^ 5 5^ 5')
            extract_onsite_chemical(H)
Ejemplo n.º 25
0
    def test_too_many_terms(self):
        """Test exception raised for wrong number of terms"""
        with pytest.raises(BoseHubbardError):
            H = bose_hubbard(2, 2, 1, 0)
            H -= BosonOperator('0^ 1^')
            extract_tunneling(H)

        with pytest.raises(BoseHubbardError):
            H = bose_hubbard(2, 2, 1, 0)
            H -= BosonOperator('0^ 1')
            H -= BosonOperator('1^ 0')
            extract_tunneling(H)
Ejemplo n.º 26
0
    def test_commutes_no_intersection(self):
        com = commutator(FermionOperator('2^ 3'), FermionOperator('4^ 5^ 3'))
        com = normal_ordered(com)
        self.assertEqual(com, FermionOperator.zero())

        com = commutator(BosonOperator('2^ 3'), BosonOperator('4^ 5^ 3'))
        com = normal_ordered(com)
        self.assertTrue(com == BosonOperator.zero())

        com = commutator(QuadOperator('q2 p3'), QuadOperator('q4 q5 p3'))
        com = normal_ordered(com)
        self.assertTrue(com == QuadOperator.zero())
    def test_number_operator_nosite(self):
        op = number_operator(4, parity=-1)
        expected = (FermionOperator(((0, 1), (0, 0))) + FermionOperator(
            ((1, 1), (1, 0))) + FermionOperator(
                ((2, 1), (2, 0))) + FermionOperator(((3, 1), (3, 0))))
        self.assertEqual(op, expected)

        op = number_operator(4, parity=1)
        expected = (BosonOperator(((0, 1), (0, 0))) + BosonOperator(
            ((1, 1), (1, 0))) + BosonOperator(
                ((2, 1), (2, 0))) + BosonOperator(((3, 1), (3, 0))))
        self.assertTrue(op == expected)
Ejemplo n.º 28
0
    def test_symmetric_non_hermitian(self):
        op = BosonOperator('0^ 0')
        res = symmetric_ordering(op)
        expected = BosonOperator('0^ 0', 0.5) \
            + BosonOperator('0 0^', 0.5)
        self.assertTrue(res == expected)
        self.assertTrue(is_hermitian(res))

        op = QuadOperator('q0 p0')
        res = symmetric_ordering(op)
        expected = QuadOperator('q0 p0', 0.5) \
            + QuadOperator('p0 q0', 0.5)
        self.assertTrue(res == expected)
        self.assertTrue(is_hermitian(res))
Ejemplo n.º 29
0
def cross_kerr(kappa, cutoff):
    r"""Cross-Kerr interaction e^{-i\kappa n_1 n_2}.

    Args:
        kappa (float): Kerr interaction strength.
        cutoff (int): the Fock basis truncation of the returned unitary.

    Returns:
        array: a [cutoff, cutoff] complex array representing
            the action of the cross-Kerr interaction in the truncated
            Fock basis.
    """
    n0 = BosonOperator('0^ 0')
    n1 = BosonOperator('1^ 1')
    U = expm(get_sparse_operator(1j*kappa*n0*n1, trunc=cutoff).toarray())
    return U
Ejemplo n.º 30
0
 def test_two_mode(self):
     b = BosonOperator('0^ 2')
     q = get_quad_operator(b, hbar=self.hbar)
     expected = QuadOperator('q0') - 1j * QuadOperator('p0')
     expected *= (QuadOperator('q2') + 1j * QuadOperator('p2'))
     expected /= 2 * self.hbar
     self.assertTrue(q == expected)