def test_error_operator(self): FO = FermionOperator terms = [] for i in range(4): terms.append(FO(((i, 1), ((i + 1) % 4, 0)), -0.0123370055014)) terms.append(FO(((i, 1), ((i - 1) % 4, 0)), -0.0123370055014)) if i in [0, 2]: terms.append( normal_ordered( FO(((i + 1, 1), (i, 1), (i + 1, 0), (i, 0)), 3.18309886184))) if i < 2: terms.append( normal_ordered( FO(((i, 1), ((i + 2) % 4, 1), (i, 0), ((i + 2) % 4, 0)), 22.2816920329))) self.assertAlmostEqual( low_depth_second_order_trotter_error_operator(terms).terms[((3, 1), (2, 1), (1, 1), (2, 0), (1, 0), (0, 0))], 0.75)
def double_commutator(op1, op2, op3, indices2=None, indices3=None, is_hopping_operator2=None, is_hopping_operator3=None): """Return the double commutator [op1, [op2, op3]]. Args: op1, op2, op3 (FermionOperators or BosonOperators): operators for the commutator. All three operators must be of the same type. indices2, indices3 (set): The indices op2 and op3 act on. is_hopping_operator2 (bool): Whether op2 is a hopping operator. is_hopping_operator3 (bool): Whether op3 is a hopping operator. Returns: The double commutator of the given operators. """ if is_hopping_operator2 and is_hopping_operator3: indices2 = set(indices2) indices3 = set(indices3) # Determine which indices both op2 and op3 act on. try: intersection, = indices2.intersection(indices3) except ValueError: return FermionOperator.zero() # Remove the intersection from the set of indices, since it will get # cancelled out in the final result. indices2.remove(intersection) indices3.remove(intersection) # Find the indices of the final output hopping operator. index2, = indices2 index3, = indices3 coeff2 = op2.terms[list(op2.terms)[0]] coeff3 = op3.terms[list(op3.terms)[0]] commutator23 = (FermionOperator( ((index2, 1), (index3, 0)), coeff2 * coeff3) + FermionOperator( ((index3, 1), (index2, 0)), -coeff2 * coeff3)) else: commutator23 = normal_ordered(commutator(op2, op3)) return normal_ordered(commutator(op1, commutator23))
def test_sum_of_ordered_terms_equals_full_hamiltonian_odd_side_len(self): hamiltonian = normal_ordered( fermi_hubbard(5, 5, 1.0, -0.3, periodic=False)) hamiltonian.compress() terms = simulation_ordered_grouped_hubbard_terms_with_info( hamiltonian)[0] terms_total = sum(terms, FermionOperator.zero()) self.assertTrue(terms_total == hamiltonian)
def test_total_length_odd_side_length_full_hubbard(self): hamiltonian = normal_ordered( fermi_hubbard(5, 5, -1., -0.3, periodic=False)) hamiltonian.compress() # Unpack result into terms, indices they act on, and whether they're # hopping operators. result = simulation_ordered_grouped_hubbard_terms_with_info( hamiltonian) terms, _, _ = result self.assertEqual(len(terms), 105)
def test_total_length_even_side_length_onsite_only(self): hamiltonian = normal_ordered( fermi_hubbard(4, 4, 0., -0.3, periodic=False)) hamiltonian.compress() # Unpack result into terms, indices they act on, and whether they're # hopping operators. result = simulation_ordered_grouped_hubbard_terms_with_info( hamiltonian) terms, indices, is_hopping = result self.assertEqual(len(terms), 16)
def get_qubit_expectations(self, qubit_operator): """Return expectations of QubitOperator in new QubitOperator. Args: qubit_operator: QubitOperator instance to be evaluated on this InteractionRDM. Returns: QubitOperator: QubitOperator with coefficients corresponding to expectation values of those operators. Raises: InteractionRDMError: Observable not contained in 1-RDM or 2-RDM. """ from openfermion.transforms import reverse_jordan_wigner from openfermion.utils._operator_utils import normal_ordered qubit_operator_expectations = copy.deepcopy(qubit_operator) for qubit_term in qubit_operator_expectations.terms: expectation = 0. # Map qubits back to fermions. reversed_fermion_operators = reverse_jordan_wigner( QubitOperator(qubit_term)) reversed_fermion_operators = normal_ordered( reversed_fermion_operators) # Loop through fermion terms. for fermion_term in reversed_fermion_operators.terms: coefficient = reversed_fermion_operators.terms[fermion_term] # Handle molecular term. if FermionOperator( fermion_term).is_two_body_number_conserving(): if not fermion_term: expectation += coefficient else: indices = [operator[0] for operator in fermion_term] if len(indices) == 2: # One-body term indices = tuple(zip(indices, (1, 0))) else: # Two-body term indices = tuple(zip(indices, (1, 1, 0, 0))) rdm_element = self[indices] expectation += rdm_element * coefficient # Handle non-molecular terms. elif len(fermion_term) > 4: raise InteractionRDMError('Observable not contained ' 'in 1-RDM or 2-RDM.') qubit_operator_expectations.terms[qubit_term] = expectation return qubit_operator_expectations
def test_sum_of_ordered_terms_equals_full_side_length_2_hopping_only(self): hamiltonian = normal_ordered( fermi_hubbard(2, 2, 1., 0.0, periodic=False)) hamiltonian.compress() # Unpack result into terms, indices they act on, and whether they're # hopping operators. result = simulation_ordered_grouped_hubbard_terms_with_info( hamiltonian) terms, _, _ = result terms_total = sum(terms, FermionOperator.zero()) self.assertTrue(terms_total == hamiltonian)
def test_error_bound_using_info_even_side_length(self): # Generate the Hamiltonian. hamiltonian = normal_ordered( fermi_hubbard(4, 4, 0.5, 0.2, periodic=False)) hamiltonian.compress() # Unpack result into terms, indices they act on, and whether they're # hopping operators. result = simulation_ordered_grouped_hubbard_terms_with_info( hamiltonian) terms, indices, is_hopping = result self.assertAlmostEqual( low_depth_second_order_trotter_error_bound(terms, indices, is_hopping), 13.59)
def test_is_hopping_operator_terms_with_info(self): hamiltonian = normal_ordered( fermi_hubbard(5, 5, 1., -1., periodic=False)) hamiltonian.compress() # Unpack result into terms, indices they act on, and whether they're # hopping operators. result = simulation_ordered_grouped_hubbard_terms_with_info( hamiltonian) terms, _, is_hopping = result for i in range(len(terms)): single_term = list(terms[i].terms)[0] is_hopping_term = not (single_term[1][1] or single_term[0][0] == single_term[1][0]) self.assertEqual(is_hopping_term, is_hopping[i])
def test_correct_indices_terms_with_info(self): hamiltonian = normal_ordered( fermi_hubbard(5, 5, 1., -1., periodic=False)) hamiltonian.compress() # Unpack result into terms, indices they act on, and whether they're # hopping operators. result = simulation_ordered_grouped_hubbard_terms_with_info( hamiltonian) terms, indices, _ = result for i in range(len(terms)): term = list(terms[i].terms) term_indices = set() for single_term in term: term_indices = term_indices.union( [single_term[j][0] for j in range(len(single_term))]) self.assertEqual(term_indices, indices[i])