def get_quad_operator(operator, hbar=1.): """Convert to QuadOperator. Args: operator: BosonOperator. 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: quad_operator: An instance of the QuadOperator class. """ quad_operator = QuadOperator() if isinstance(operator, BosonOperator): for term, coefficient in operator.terms.items(): tmp = QuadOperator('', coefficient) for i, d in term: tmp *= (1./numpy.sqrt(2.*hbar)) \ * (QuadOperator(((i, 'q'))) + QuadOperator(((i, 'p')), 1j*(-1)**d)) quad_operator += tmp else: raise TypeError("Only BosonOperator is currently " "supported for get_quad_operator.") return quad_operator
def test_quad_form(self, hbar): """Test it has the correct form using quadrature operators""" H, _ = beamsplitter(np.pi / 4, np.pi / 2, mode1=1, mode2=3, hbar=hbar) H = normal_ordered(get_quad_operator(H, hbar=hbar), hbar=hbar) expected = QuadOperator('q1 q3', -1) expected += QuadOperator('p1 p3', -1) assert H == expected
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)
def test_quad_form(self, hbar): """Test it has the correct form using quadrature operators""" H, _ = two_mode_squeezing(2, mode1=1, mode2=3, hbar=hbar) H = normal_ordered(get_quad_operator(H, hbar=hbar), hbar=hbar) expected = QuadOperator('q1 p3', 1) expected += QuadOperator('p1 q3', 1) assert H == expected
def test_quad_form(self, hbar): """Test it has the correct form using quadrature operators""" H, _ = squeezing(2, mode=1) H = normal_ordered(get_quad_operator(H, hbar=hbar), hbar=hbar) expected = QuadOperator('q1 p1', -1) expected += QuadOperator('', 1j) assert H == expected
def test_displaced_oscillator(self): """Test that a forced quantum oscillator produces the correct self.logTestName() trajectory in the phase space""" H = QuadOperator('q0 q0', 0.5) H += QuadOperator('p0 p0', 0.5) H -= QuadOperator('q0', self.F) res = [] tlist = np.arange(0, self.t, self.dt) for t in tlist: #pylint: disable=unused-variable self.eng.reset() q = self.eng.register with self.eng: Xgate(self.x0) | q[0] Zgate(self.p0) | q[0] GaussianPropagation(H, self.t) | q state = self.eng.run('gaussian') res.append(state.means().tolist()) res = np.array(res)[-1] expected = self.displaced_oscillator_soln(self.t) self.assertTrue(np.allclose(res, expected))
def test_displaced_oscillator(self): """Test that a forced quantum oscillator produces the correct self.logTestName() trajectory in the phase space""" H = QuadOperator('q0 q0', 0.5) H += QuadOperator('p0 p0', 0.5) H -= QuadOperator('q0', self.F) res = [] tlist = np.arange(0, self.t, self.dt) eng = sf.Engine("gaussian") for idx, t in enumerate(tlist): #pylint: disable=unused-variable prog = sf.Program(1) with prog.context as q: Xgate(self.x0) | q[0] Zgate(self.p0) | q[0] GaussianPropagation(H, self.t) | q state = eng.run(prog).state eng.reset() res.append(state.means().tolist()) res = np.array(res)[-1] expected = self.displaced_oscillator_soln(self.t) assert np.allclose(res, expected)
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
def test_quad_form(self, hbar): """Test it has the correct form using quadrature operators""" H, _ = rotation(self.phi, mode=1, hbar=hbar) H = normal_ordered(get_quad_operator(H, hbar=hbar), hbar=hbar) expected = QuadOperator('q1 q1', -1 / hbar) expected += QuadOperator('p1 p1', -1 / hbar) expected += QuadOperator('', 1) assert H == expected
def test_symmetric_coefficient(self): coeff = 0.5+0.6j op = QuadOperator('q0 p0', coeff) res = symmetric_ordering(op, ignore_coeff=False) expected = QuadOperator('q0 p0', 0.5) \ + QuadOperator('p0 q0', 0.5) self.assertTrue(res == coeff*expected) self.assertFalse(is_hermitian(res))
def test_quad_form(self): """Test it has the correct form using quadrature operators""" self.logTestName() H, _ = two_mode_squeezing(2, mode1=1, mode2=3, hbar=self.hbar) H = normal_ordered(get_quad_operator(H, hbar=self.hbar), hbar=self.hbar) expected = QuadOperator('q1 p3', 1) expected += QuadOperator('p1 q3', 1) self.assertEqual(H, expected)
def test_two_term(self): q = QuadOperator('p0 q0') + QuadOperator('q0 p0') b = get_boson_operator(q, hbar=self.hbar) expected = -1j*self.hbar/2 \ * ((BosonOperator('0') + BosonOperator('0^')) * (BosonOperator('0') - BosonOperator('0^')) + (BosonOperator('0') - BosonOperator('0^')) * (BosonOperator('0') + BosonOperator('0^'))) self.assertTrue(b == expected)
def test_quad_form(self): """Test it has the correct form using quadrature operators""" self.logTestName() H, _ = squeezing(2, mode=1) H = normal_ordered(get_quad_operator(H, hbar=self.hbar), hbar=self.hbar) expected = QuadOperator('q1 p1', -1) expected += QuadOperator('', 1j) self.assertEqual(H, expected)
def normal_ordered_quad_term(term, coefficient, hbar=1.): """Return a normal ordered QuadOperator corresponding to single term. Args: term: A tuple of tuples. The first element of each tuple is an integer indicating the mode on which a boson ladder operator acts, starting from zero. The second element of each tuple is an integer, either 1 or 0, indicating whether creation or annihilation acts on that mode. coefficient: The coefficient of the term. 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: ordered_term (QuadOperator): The normal ordered form of the input. Note that this might have more terms. In our convention, normal ordering implies terms are ordered from highest tensor factor (on left) to lowest (on right). Also, q operators come first. """ # Iterate from left to right across operators and reorder to normal # form. Swap terms operators into correct position by moving from # left to right across ladder operators. term = list(term) ordered_term = QuadOperator() for i in range(1, len(term)): for j in range(i, 0, -1): right_operator = term[j] left_operator = term[j - 1] # Swap operators if q on right and p on left. # p q -> q p if right_operator[1] == 'q' and not left_operator[1] == 'q': term[j - 1] = right_operator term[j] = left_operator # Replace p q with i hbar + q p # if indices are the same. if right_operator[0] == left_operator[0]: new_term = term[:(j - 1)] + term[(j + 1)::] # Recursively add the processed new term. ordered_term += normal_ordered_quad_term( tuple(new_term), -coefficient * 1j * hbar) # Handle case when operator type is the same. elif right_operator[1] == left_operator[1]: # Swap if same type but lower index on left. if right_operator[0] > left_operator[0]: term[j - 1] = right_operator term[j] = left_operator # Add processed term and return. ordered_term += QuadOperator(tuple(term), coefficient) return ordered_term
def test_quad_form(self): """Test it has the correct form using quadrature operators""" self.logTestName() H, _ = rotation(self.phi, mode=1, hbar=self.hbar) H = normal_ordered(get_quad_operator(H, hbar=self.hbar), hbar=self.hbar) expected = QuadOperator('q1 q1', -0.5) expected += QuadOperator('p1 p1', -0.5) expected += QuadOperator('', 1) self.assertEqual(H, expected)
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())
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_weyl_non_hermitian(self): res = weyl_polynomial_quantization('q0 p0') expected = QuadOperator('q0 p0', 0.5) \ + QuadOperator('p0 q0', 0.5) self.assertTrue(res == expected) self.assertTrue(is_hermitian(res)) res = weyl_polynomial_quantization('q0^2 p0') expected = QuadOperator('q0 q0 p0', 0.5) \ + QuadOperator('p0 q0 q0', 0.5) self.assertTrue(res == expected) self.assertTrue(is_hermitian(res))
def test_quad_form(self): """Test it has the correct form using quadrature operators""" self.logTestName() H, _ = beamsplitter(np.pi / 4, np.pi / 2, mode1=1, mode2=3, hbar=self.hbar) H = normal_ordered(get_quad_operator(H, hbar=self.hbar), hbar=self.hbar) expected = QuadOperator('q1 q3', -1) expected += QuadOperator('p1 p3', -1) self.assertEqual(H, expected)
def test_singular_coefficients(self): """Test that H=p^2/2+q has displacement (q,t)=(-t^2,-t)""" self.eng.reset() q = self.eng.register H = QuadOperator('p0 p0', 0.5) + QuadOperator('q0') with self.eng: GaussianPropagation(H, self.t) | q[0] state = self.eng.run('gaussian') res = state.means() expected = [-self.t**2 / 2, -self.t] self.assertTrue(np.allclose(res, expected))
def test_singular_coefficients(self): """Test that H=p^2/2+q has displacement (q,t)=(-t^2,-t)""" prog = sf.Program(1) eng = sf.Engine("gaussian") H = QuadOperator('p0 p0', 0.5) + QuadOperator('q0') with prog.context as q: GaussianPropagation(H, self.t) | q[0] state = eng.run(prog).state res = state.means() expected = [-self.t**2 / 2, -self.t] assert np.allclose(res, expected)
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))
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)
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)
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)
def test_displacement_vector(self): """Test displacement vector extracted""" H = QuadOperator('q0', -0.432) + QuadOperator('p0', 3.213) A, d = quadratic_coefficients(H) expected_A = np.zeros([2, 2]) expected_d = np.array([3.213, 0.432]) assert np.allclose(A, expected_A) assert np.allclose(d, expected_d) _, d = quadratic_coefficients(QuadOperator('q0 q0')) expected = np.array([0, 0]) assert np.allclose(d, expected) _, d = quadratic_coefficients(QuadOperator('p0 p1')) expected = np.array([0, 0, 0, 0]) assert np.allclose(d, expected)
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)
def test_symmetric_two_term_same(self): op = BosonOperator('0^ 0^') res = symmetric_ordering(op) self.assertTrue(res == op) op = QuadOperator('q0 q0') res = symmetric_ordering(op) self.assertTrue(res == op)
def test_symmetric_one_term_multimode(self): op = BosonOperator('0^ 1^ 2 3') res = symmetric_ordering(op) self.assertTrue(res == op) op = QuadOperator('q0 q1 p2 p3') res = symmetric_ordering(op) self.assertTrue(res == op)
def test_symmetric_non_hermitian_order(self): op1 = QuadOperator('q0 p0 q0') op2 = QuadOperator('q0 q0 p0') op3 = QuadOperator('p0 q0 q0') w1 = symmetric_ordering(op1) w2 = symmetric_ordering(op2) w3 = symmetric_ordering(op3) self.assertTrue(is_hermitian(w1)) self.assertTrue(is_hermitian(w2)) self.assertTrue(is_hermitian(w3)) expected = QuadOperator('q0 q0 p0', 0.5) \ + QuadOperator('p0 q0 q0', 0.5) self.assertTrue(w1 == expected) self.assertTrue(w2 == expected) self.assertTrue(w3 == expected)