diff --git a/src/openfermion/utils/_dual_basis_trotter_error.py b/src/openfermion/utils/_dual_basis_trotter_error.py index 1c6c4d253..4eff97047 100644 --- a/src/openfermion/utils/_dual_basis_trotter_error.py +++ b/src/openfermion/utils/_dual_basis_trotter_error.py @@ -192,7 +192,7 @@ def stagger_with_info(hamiltonian, input_ordering, parity): Groups terms into hopping (i^ j + j^ i) and number (i^j^ i j + c_i i^ i + c_j j^ j) operators. Pre-computes term information (indices each operator acts on, as - well as whether each operator is a hopping operator. + well as whether each operator is a hopping operator). Args: hamiltonian (FermionOperator): The Hamiltonian. @@ -204,6 +204,12 @@ def stagger_with_info(hamiltonian, input_ordering, parity): A 3-tuple of terms from the Hamiltonian that are simulated in the stagger, the indices they act on, and whether they are hopping operators (all in the same order). + + Notes: + The "staggers" used here are the left (parity=False) and right + (parity=True) staggers detailed in Kivlichan et al., "Quantum + Simulation of Electronic Structure with Linear Depth and + Connectivity", arxiv:1711.04789. """ terms_in_step = [] indices_in_step = [] diff --git a/src/openfermion/utils/_hubbard_trotter_error.py b/src/openfermion/utils/_hubbard_trotter_error.py index d7ca85e97..7c3e2e7b1 100644 --- a/src/openfermion/utils/_hubbard_trotter_error.py +++ b/src/openfermion/utils/_hubbard_trotter_error.py @@ -12,67 +12,13 @@ """Module to compute Trotter errors in the plane-wave dual basis.""" from __future__ import absolute_import -from future.utils import iteritems, itervalues import numpy from openfermion.config import * -from openfermion.hamiltonians import fermi_hubbard from openfermion.ops import FermionOperator, normal_ordered from openfermion.utils import count_qubits -from openfermion.utils._dual_basis_trotter_error import ( - dual_basis_error_bound, dual_basis_error_operator, stagger_with_info) - - -def fermi_hubbard_error_operator(terms, indices=None, is_hopping_operator=None, - verbose=False): - """Determine the difference between the exact generator of unitary - evolution and the approximate generator given by the second-order - Trotter-Suzuki expansion for the Hubbard model. - - Args: - terms: a list of FermionOperators in the Hamiltonian in the - order in which they will be simulated. - indices: a set of indices the terms act on in the same order as terms. - is_hopping_operator: a list of whether each term is a hopping operator. - verbose: Whether to print percentage progress. - - Returns: - The difference between the true and effective generators of time - evolution for a single Trotter step. - - Notes: follows Equation 9 of Poulin et al.'s work in "The Trotter Step - Size Required for Accurate Quantum Simulation of Quantum Chemistry". - """ - return dual_basis_error_operator( - terms, indices=indices, is_hopping_operator=is_hopping_operator, - verbose=verbose) - - -def fermi_hubbard_error_bound(terms, indices=None, is_hopping_operator=None, - verbose=False): - """Numerically upper bound the error in the ground state energy - for the second-order Trotter-Suzuki expansion. - - Args: - terms: a list of single-term FermionOperators in the Hamiltonian - to be simulated. - indices: a set of indices the terms act on in the same order as terms. - is_hopping_operator: a list of whether each term is a hopping operator. - verbose: Whether to print percentage progress. - - Returns: - A float upper bound on norm of error in the ground state energy. - - Notes: - Follows Equation 9 of Poulin et al.'s work in "The Trotter Step - Size Required for Accurate Quantum Simulation of Quantum - Chemistry" to calculate the error operator. - """ - # Return the 1-norm of the error operator (upper bound on error). - return dual_basis_error_bound( - terms, indices=indices, is_hopping_operator=is_hopping_operator, - verbose=verbose) +from openfermion.utils._dual_basis_trotter_error import stagger_with_info def simulation_ordered_grouped_hubbard_terms_with_info( @@ -80,9 +26,9 @@ def simulation_ordered_grouped_hubbard_terms_with_info( """Give terms from the Fermi-Hubbard Hamiltonian in simulated order. Uses the simulation ordering, grouping terms into hopping - (i^ j + j^ i) and number (i^j^ i j + c_i i^ i + c_j j^ j) operators. + (i^ j + j^ i) and on-site potential (i^j^ i j) operators. Pre-computes term information (indices each operator acts on, as - well as whether each operator is a hopping operator. + well as whether each operator is a hopping operator). Args: hubbard_hamiltonian (FermionOperator): The Hamiltonian. @@ -95,7 +41,10 @@ def simulation_ordered_grouped_hubbard_terms_with_info( Notes: Assumes that the Hubbard model has spin and is on a 2D square - aperiodic lattice. + aperiodic lattice. Uses the "stagger"-based Trotter step for the + Hubbard model detailed in Kivlichan et al., "Quantum Simulation + of Electronic Structure with Linear Depth and Connectivity", + arxiv:1711.04789. """ hamiltonian = normal_ordered(hubbard_hamiltonian) n_qubits = count_qubits(hamiltonian) diff --git a/src/openfermion/utils/_hubbard_trotter_error_test.py b/src/openfermion/utils/_hubbard_trotter_error_test.py index b16231cc3..c48fdf2ed 100644 --- a/src/openfermion/utils/_hubbard_trotter_error_test.py +++ b/src/openfermion/utils/_hubbard_trotter_error_test.py @@ -16,6 +16,8 @@ from openfermion.ops import FermionOperator, normal_ordered from openfermion.hamiltonians import fermi_hubbard from openfermion.utils._hubbard_trotter_error import * +from openfermion.utils._dual_basis_trotter_error import ( + dual_basis_error_bound, dual_basis_error_operator) class ErrorOperatorTest(unittest.TestCase): @@ -37,7 +39,7 @@ def test_error_operator(self): 22.2816920329))) self.assertAlmostEqual( - fermi_hubbard_error_operator(terms).terms[ + dual_basis_error_operator(terms).terms[ ((3, 1), (2, 1), (1, 1), (2, 0), (1, 0), (0, 0))], 0.75) @@ -60,7 +62,7 @@ def test_error_bound_superset_hubbard(self): set([1, 3]), set([1, 3])] is_hopping_operator = [True, True, True, False, True, False] - self.assertAlmostEqual(fermi_hubbard_error_bound( + self.assertAlmostEqual(dual_basis_error_bound( terms, indices, is_hopping_operator), 0.0608) def test_error_bound_using_info_even_side_length(self): @@ -75,7 +77,7 @@ def test_error_bound_using_info_even_side_length(self): hamiltonian) terms, indices, is_hopping = result - self.assertAlmostEqual(fermi_hubbard_error_bound( + self.assertAlmostEqual(dual_basis_error_bound( terms, indices, is_hopping), 13.59) def test_error_bound_using_info_odd_side_length_verbose(self): @@ -90,7 +92,7 @@ def test_error_bound_using_info_odd_side_length_verbose(self): hamiltonian) terms, indices, is_hopping = result - self.assertAlmostEqual(32.025, fermi_hubbard_error_bound( + self.assertAlmostEqual(32.025, dual_basis_error_bound( terms, indices, is_hopping, verbose=True))