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_operator_hermitian(self): op = QuadOperator('q0 p1 q2 p3') self.assertTrue(is_hermitian(op)) op = QuadOperator('q0 p0 q1 p1') op += QuadOperator('p0 q0 p1 q1') self.assertTrue(is_hermitian(op))
def test_quad_single_term(self): op = QuadOperator('p4 p3 p2 p1') + QuadOperator('p3 p2') self.assertTrue(op == normal_ordered(op)) op = QuadOperator('q0 p0') - QuadOperator('p0 q0') expected = QuadOperator('', 2.j) self.assertTrue(expected == normal_ordered(op, hbar=2.))
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 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_triple(self): op_132 = QuadOperator(((1, 'p'), (3, 'q'), (2, 'q'))) op_123 = QuadOperator(((1, 'p'), (2, 'q'), (3, 'q'))) op_321 = QuadOperator(((3, 'q'), (2, 'q'), (1, 'p'))) self.assertTrue(op_132 == normal_ordered(op_123)) self.assertTrue(op_132 == normal_ordered(op_132)) self.assertTrue(op_132 == normal_ordered(op_321))
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_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 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_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_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_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_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_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_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_reorder_quad(self): shift_by_one = lambda x, y: (x + 1) % y operator = QuadOperator('q1 q2 p3 p4', -3.17) reordered = reorder(operator, shift_by_one) self.assertEqual(reordered.terms, {((0, 'p'), (2, 'q'), (3, 'q'), (4, 'p')): -3.17}) reordered = reorder(operator, shift_by_one, reverse=True) self.assertEqual(reordered.terms, {((0, 'q'), (1, 'q'), (2, 'p'), (3, 'p')): -3.17})
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)
def setUp(self): self.fermion_term = FermionOperator('1^ 2^ 3 4', -3.17) self.fermion_operator = self.fermion_term + hermitian_conjugated( self.fermion_term) self.boson_term = BosonOperator('1^ 2^ 3 4', -3.17) self.boson_operator = self.boson_term + hermitian_conjugated( self.boson_term) self.quad_term = QuadOperator('q0 p0 q1 p0 p0', -3.17) self.quad_operator = self.quad_term + hermitian_conjugated( self.quad_term) self.qubit_operator = jordan_wigner(self.fermion_operator)
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 = BosonOperator('0^ 0', 0.5) res = symmetric_ordering(op, ignore_coeff=False) expected = BosonOperator('0^ 0', 0.25) \ + BosonOperator('0 0^', 0.25) 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_eigenspectrum(self): fermion_eigenspectrum = eigenspectrum(self.fermion_operator) qubit_eigenspectrum = eigenspectrum(self.qubit_operator) interaction_eigenspectrum = eigenspectrum(self.interaction_operator) for i in range(2**self.n_qubits): self.assertAlmostEqual(fermion_eigenspectrum[i], qubit_eigenspectrum[i]) self.assertAlmostEqual(fermion_eigenspectrum[i], interaction_eigenspectrum[i]) with self.assertRaises(TypeError): _ = eigenspectrum(BosonOperator()) with self.assertRaises(TypeError): _ = eigenspectrum(QuadOperator())
def setUp(self): self.n_qubits = 5 self.fermion_term = FermionOperator('1^ 2^ 3 4', -3.17) self.fermion_operator = self.fermion_term + hermitian_conjugated( self.fermion_term) self.boson_term = BosonOperator('1^ 2^ 3 4', -3.17) self.boson_operator = self.boson_term + hermitian_conjugated( self.boson_term) self.quad_term = QuadOperator('q0 p0 q1 p0 p0', -3.17) self.quad_operator = self.quad_term + hermitian_conjugated( self.quad_term) self.qubit_operator = jordan_wigner(self.fermion_operator) self.file_name = "test_file" self.bad_operator_filename = 'bad_file.data' bad_op = "A:\nB" with open(os.path.join(DATA_DIRECTORY, self.bad_operator_filename), 'w') as fid: fid.write(bad_op)
def test_canonical_quad_commutation_relations(self): q1 = QuadOperator('q3') p1 = QuadOperator('p3') q2 = QuadOperator('q4') p2 = QuadOperator('p4') zero = QuadOperator() one = QuadOperator('') hbar = 2. self.assertTrue(1j * hbar * one == normal_ordered(commutator(q1, p1), hbar)) self.assertTrue(zero == normal_ordered(commutator(q1, q2), hbar)) self.assertTrue(zero == normal_ordered(commutator(q1, p2), hbar)) self.assertTrue(zero == normal_ordered(commutator(p1, q2), hbar)) self.assertTrue(zero == normal_ordered(commutator(p1, p2), hbar)) self.assertTrue(1j * hbar * one == normal_ordered(commutator(q2, p2), hbar))
def test_is_identity_double_of_unit_quadoperator(self): self.assertTrue(is_identity(2. * QuadOperator(())))
def test_is_identity_unit_quadoperator(self): self.assertTrue(is_identity(QuadOperator(())))
def test_quad_operator_nonhermitian(self): op = QuadOperator('q0 p1 q1') self.assertFalse(is_hermitian(op))
def test_quad_operator_identity(self): op = QuadOperator(()) self.assertTrue(is_hermitian(op))
def test_quad_operator_zero(self): op = QuadOperator() self.assertTrue(is_hermitian(op))