def benchmark_fermion_math_and_normal_order(n_qubits, term_length, power): """Benchmark both arithmetic operators and normal ordering on fermions. The idea is we generate two random FermionTerms, A and B, each acting on n_qubits with term_length operators. We then compute (A + B) ** power. This is costly that is the first benchmark. The second benchmark is in normal ordering whatever comes out. Args: n_qubits: The number of qubits on which these terms act. term_length: The number of operators in each term. power: Int, the exponent to which to raise sum of the two terms. Returns: runtime_math: The time it takes to perform (A + B) ** power runtime_normal_order: The time it takes to perform FermionOperator.normal_order() """ # Generate random operator strings. operators_a = [(numpy.random.randint(n_qubits), numpy.random.randint(2))] operators_b = [(numpy.random.randint(n_qubits), numpy.random.randint(2))] for _ in range(term_length): # Make sure the operator is not trivially zero. operator_a = (numpy.random.randint(n_qubits), numpy.random.randint(2)) while operator_a == operators_a[-1]: operator_a = (numpy.random.randint(n_qubits), numpy.random.randint(2)) operators_a += [operator_a] # Do the same for the other operator. operator_b = (numpy.random.randint(n_qubits), numpy.random.randint(2)) while operator_b == operators_b[-1]: operator_b = (numpy.random.randint(n_qubits), numpy.random.randint(2)) operators_b += [operator_b] # Initialize FermionTerms and then sum them together. fermion_term_a = FermionOperator(tuple(operators_a), float(numpy.random.randn())) fermion_term_b = FermionOperator(tuple(operators_b), float(numpy.random.randn())) fermion_operator = fermion_term_a + fermion_term_b # Exponentiate. start_time = time.time() fermion_operator **= power runtime_math = time.time() - start_time # Normal order. start_time = time.time() normal_ordered(fermion_operator) runtime_normal_order = time.time() - start_time # Return. return runtime_math, runtime_normal_order
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 test_integration_jellium_hamiltonian_with_negation(self): hamiltonian = normal_ordered( jellium_model(Grid(2, 3, 1.), plane_wave=False)) part_a = FermionOperator.zero() part_b = FermionOperator.zero() add_to_a_or_b = 0 # add to a if 0; add to b if 1 for term, coeff in hamiltonian.terms.items(): # Partition terms in the Hamiltonian into part_a or part_b if add_to_a_or_b: part_a += FermionOperator(term, coeff) else: part_b += FermionOperator(term, coeff) add_to_a_or_b ^= 1 reference = normal_ordered(commutator(part_a, part_b)) result = commutator_ordered_diagonal_coulomb_with_two_body_operator( part_a, part_b) self.assertTrue(result.isclose(reference)) negative = commutator_ordered_diagonal_coulomb_with_two_body_operator( part_b, part_a) result += negative self.assertTrue(result.isclose(FermionOperator.zero()))
def test_majorana_form(self): """Test getting the Majorana form.""" majorana_matrix, majorana_constant = self.quad_ham_npc.majorana_form() # Convert the Majorana form to a FermionOperator majorana_op = FermionOperator((), majorana_constant) normalization = 1. / numpy.sqrt(2.) for i in range(2 * self.n_qubits): if i < self.n_qubits: left_op = majorana_operator((i, 0), normalization) else: left_op = majorana_operator((i - self.n_qubits, 1), normalization) for j in range(2 * self.n_qubits): if j < self.n_qubits: right_op = majorana_operator( (j, 0), majorana_matrix[i, j] * normalization) else: right_op = majorana_operator( (j - self.n_qubits, 1), majorana_matrix[i, j] * normalization) majorana_op += .5j * left_op * right_op # Get FermionOperator for original Hamiltonian fermion_operator = normal_ordered( get_fermion_operator(self.quad_ham_npc)) self.assertTrue(normal_ordered(majorana_op) == fermion_operator)
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())
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))
def test_ccr_onsite(self): c1 = FermionOperator(((1, 1), )) a1 = hermitian_conjugated(c1) self.assertTrue( normal_ordered(c1 * a1) == FermionOperator(()) - normal_ordered(a1 * c1)) self.assertTrue( jordan_wigner(c1 * a1) == QubitOperator(()) - jordan_wigner(a1 * c1))
def test_jordan_wigner_twobody_interaction_op_allunique(self): test_op = FermionOperator('1^ 2^ 3 4') test_op += hermitian_conjugated(test_op) retransformed_test_op = reverse_jordan_wigner( jordan_wigner(get_interaction_operator(test_op))) self.assertTrue( normal_ordered(retransformed_test_op) == normal_ordered(test_op))
def test_inverse_fourier_transform_2d(self): grid = Grid(dimensions=2, scale=1.5, length=3) spinless = True geometry = [('H', (0, 0)), ('H', (0.5, 0.8))] h_plane_wave = plane_wave_hamiltonian(grid, geometry, spinless, True) h_dual_basis = plane_wave_hamiltonian(grid, geometry, spinless, False) h_dual_basis_t = inverse_fourier_transform(h_dual_basis, grid, spinless) self.assertEqual(normal_ordered(h_dual_basis_t), normal_ordered(h_plane_wave))
def test_uccsd_singlet_builds(self): """Test specific builds of the UCCSD singlet operator""" # Build 1 n_orbitals = 4 n_electrons = 2 n_params = uccsd_singlet_paramsize(n_orbitals, n_electrons) self.assertEqual(n_params, 2) initial_amplitudes = [1., 2.] generator = uccsd_singlet_generator(initial_amplitudes, n_orbitals, n_electrons) test_generator = (FermionOperator("2^ 0", 1.) + FermionOperator("0^ 2", -1.) + FermionOperator("3^ 1", 1.) + FermionOperator("1^ 3", -1.) + FermionOperator("2^ 0 3^ 1", 4.) + FermionOperator("1^ 3 0^ 2", -4.)) self.assertEqual(normal_ordered(test_generator), normal_ordered(generator)) # Build 2 n_orbitals = 6 n_electrons = 2 n_params = uccsd_singlet_paramsize(n_orbitals, n_electrons) self.assertEqual(n_params, 5) initial_amplitudes = numpy.arange(1, n_params + 1, dtype=float) generator = uccsd_singlet_generator(initial_amplitudes, n_orbitals, n_electrons) test_generator = ( FermionOperator("2^ 0", 1.) + FermionOperator("0^ 2", -1) + FermionOperator("3^ 1", 1.) + FermionOperator("1^ 3", -1.) + FermionOperator("4^ 0", 2.) + FermionOperator("0^ 4", -2) + FermionOperator("5^ 1", 2.) + FermionOperator("1^ 5", -2.) + FermionOperator("2^ 0 3^ 1", 6.) + FermionOperator("1^ 3 0^ 2", -6.) + FermionOperator("4^ 0 5^ 1", 8.) + FermionOperator("1^ 5 0^ 4", -8.) + FermionOperator("2^ 0 5^ 1", 5.) + FermionOperator("1^ 5 0^ 2", -5.) + FermionOperator("4^ 0 3^ 1", 5.) + FermionOperator("1^ 3 0^ 4", -5.) + FermionOperator("2^ 0 4^ 0", 5.) + FermionOperator("0^ 4 0^ 2", -5.) + FermionOperator("3^ 1 5^ 1", 5.) + FermionOperator("1^ 5 1^ 3", -5.)) self.assertEqual(normal_ordered(test_generator), normal_ordered(generator))
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_jordan_wigner_interaction_op_with_zero_term(self): test_op = FermionOperator('1^ 2^ 3 4') test_op += hermitian_conjugated(test_op) interaction_op = get_interaction_operator(test_op) interaction_op.constant = 0.0 retransformed_test_op = reverse_jordan_wigner( jordan_wigner(interaction_op)) self.assertEqual(normal_ordered(retransformed_test_op), normal_ordered(test_op))
def test_yy(self): yy = QubitOperator(((2, 'Y'), (3, 'Y')), 2.) transmed_yy = reverse_jordan_wigner(yy) retransmed_yy = jordan_wigner(transmed_yy) expected1 = -(FermionOperator(((2, 1), ), 2.) + FermionOperator( ((2, 0), ), 2.)) expected2 = (FermionOperator(((3, 1), )) - FermionOperator(((3, 0), ))) expected = expected1 * expected2 self.assertTrue(yy == retransmed_yy) self.assertTrue( normal_ordered(transmed_yy) == normal_ordered(expected))
def test_xy(self): xy = QubitOperator(((4, 'X'), (5, 'Y')), -2.j) transmed_xy = reverse_jordan_wigner(xy) retransmed_xy = jordan_wigner(transmed_xy) expected1 = -2j * (FermionOperator(((4, 1), ), 1j) - FermionOperator( ((4, 0), ), 1j)) expected2 = (FermionOperator(((5, 1), )) - FermionOperator(((5, 0), ))) expected = expected1 * expected2 self.assertTrue(xy == retransmed_xy) self.assertTrue( normal_ordered(transmed_xy) == normal_ordered(expected))
def test_integration_random_diagonal_coulomb_hamiltonian(self): hamiltonian1 = normal_ordered( get_fermion_operator( random_diagonal_coulomb_hamiltonian(n_qubits=7))) hamiltonian2 = normal_ordered( get_fermion_operator( random_diagonal_coulomb_hamiltonian(n_qubits=7))) reference = normal_ordered(commutator(hamiltonian1, hamiltonian2)) result = commutator_ordered_diagonal_coulomb_with_two_body_operator( hamiltonian1, hamiltonian2) self.assertTrue(result.isclose(reference))
def test_inverse_fourier_transform_1d(self): grid = Grid(dimensions=1, scale=1.5, length=4) spinless_set = [True, False] geometry = [('H', (0, )), ('H', (0.5, ))] for spinless in spinless_set: h_plane_wave = plane_wave_hamiltonian(grid, geometry, spinless, True) h_dual_basis = plane_wave_hamiltonian(grid, geometry, spinless, False) h_dual_basis_t = inverse_fourier_transform(h_dual_basis, grid, spinless) self.assertEqual(normal_ordered(h_dual_basis_t), normal_ordered(h_plane_wave))
def test_yx(self): yx = QubitOperator(((0, 'Y'), (1, 'X')), -0.5) transmed_yx = reverse_jordan_wigner(yx) retransmed_yx = jordan_wigner(transmed_yx) expected1 = 1j * (FermionOperator(((0, 1), )) + FermionOperator( ((0, 0), ))) expected2 = -0.5 * (FermionOperator(((1, 1), )) + FermionOperator( ((1, 0), ))) expected = expected1 * expected2 self.assertTrue(yx == retransmed_yx) self.assertTrue( normal_ordered(transmed_yx) == normal_ordered(expected))
def test_xx(self): xx = QubitOperator(((3, 'X'), (4, 'X')), 2.) transmed_xx = reverse_jordan_wigner(xx) retransmed_xx = jordan_wigner(transmed_xx) expected1 = (FermionOperator(((3, 1), ), 2.) - FermionOperator( ((3, 0), ), 2.)) expected2 = (FermionOperator(((4, 1), ), 1.) + FermionOperator( ((4, 0), ), 1.)) expected = expected1 * expected2 self.assertTrue(xx == retransmed_xx) self.assertTrue( normal_ordered(transmed_xx) == normal_ordered(expected))
def test_erpa_eom_ham_lih(): filename = os.path.join(DATA_DIRECTORY, "H1-Li1_sto-3g_singlet_1.45.hdf5") molecule = MolecularData(filename=filename) reduced_ham = make_reduced_hamiltonian( molecule.get_molecular_hamiltonian(), molecule.n_electrons) rha_fermion = get_fermion_operator(reduced_ham) permuted_hijkl = np.einsum('ijlk', reduced_ham.two_body_tensor) opdm = np.diag([1] * molecule.n_electrons + [0] * (molecule.n_qubits - molecule.n_electrons)) tpdm = 2 * wedge(opdm, opdm, (1, 1), (1, 1)) rdms = InteractionRDM(opdm, tpdm) dim = 3 # so we don't do the full basis. This would make the test long full_basis = {} # erpa basis. A, B basis in RPA language cnt = 0 # start from 1 to make test shorter for p, q in product(range(1, dim), repeat=2): if p < q: full_basis[(p, q)] = cnt full_basis[(q, p)] = cnt + dim * (dim - 1) // 2 cnt += 1 for rkey in full_basis.keys(): p, q = rkey for ckey in full_basis.keys(): r, s = ckey for sigma, tau in product([0, 1], repeat=2): test = erpa_eom_hamiltonian(permuted_hijkl, tpdm, 2 * q + sigma, 2 * p + sigma, 2 * r + tau, 2 * s + tau).real qp_op = FermionOperator( ((2 * q + sigma, 1), (2 * p + sigma, 0))) rs_op = FermionOperator(((2 * r + tau, 1), (2 * s + tau, 0))) erpa_op = normal_ordered( commutator(qp_op, commutator(rha_fermion, rs_op))) true = rdms.expectation(get_interaction_operator(erpa_op)) assert np.isclose(true, test)
def test_commutator(self): operator_a = ( FermionOperator('0^ 0', 0.3) + FermionOperator('1^ 1', 0.1j) + FermionOperator('1^ 0^ 1 0', -0.2) + FermionOperator('1^ 3') + FermionOperator('3^ 0') + FermionOperator('3^ 2', 0.017) - FermionOperator('2^ 3', 1.99) + FermionOperator('3^ 1^ 3 1', .09) + FermionOperator('2^ 0^ 2 0', .126j) + FermionOperator('4^ 2^ 4 2') + FermionOperator('3^ 0^ 3 0')) operator_b = ( FermionOperator('3^ 1', 0.7) + FermionOperator('1^ 3', -9.) + FermionOperator('1^ 0^ 3 0', 0.1) - FermionOperator('3^ 0^ 1 0', 0.11) + FermionOperator('3^ 2^ 3 2') + FermionOperator('3^ 1^ 3 1', -1.37) + FermionOperator('4^ 2^ 4 2') + FermionOperator('4^ 1^ 4 1') + FermionOperator('1^ 0^ 4 0', 16.7) + FermionOperator('1^ 0^ 4 3', 1.67) + FermionOperator('4^ 3^ 5 2', 1.789j) + FermionOperator('6^ 5^ 4 1', -11.789j)) reference = normal_ordered(commutator(operator_a, operator_b)) result = commutator_ordered_diagonal_coulomb_with_two_body_operator( operator_a, operator_b) diff = result - reference self.assertTrue(diff.isclose(FermionOperator.zero()))
def ordered_low_depth_terms_no_info(hamiltonian): """Give terms from Hamiltonian in dictionary output order. Args: hamiltonian (FermionOperator): The Hamiltonian. Returns: A list of terms from the Hamiltonian in simulated order. Notes: Assumes the Hamiltonian is in the form discussed in Kivlichan et al., "Quantum Simulation of Electronic Structure with Linear Depth and Connectivity", arxiv:1711.04789. This constrains the Hamiltonian to have only hopping terms (i^ j + j^ i) and potential terms which are products of at most two number operators (n_i or n_i n_j). """ count_qubits(hamiltonian) hamiltonian = normal_ordered(hamiltonian) terms = [] for operators, coefficient in hamiltonian.terms.items(): terms += [FermionOperator(operators, coefficient)] return terms
def setUp(self): geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))] basis = 'sto-3g' multiplicity = 1 filename = os.path.join(DATA_DIRECTORY, 'H2_sto-3g_singlet_0.7414') self.molecule = MolecularData(geometry, basis, multiplicity, filename=filename) self.molecule.load() # Get molecular Hamiltonian. self.molecular_hamiltonian = self.molecule.get_molecular_hamiltonian() # Get FCI RDM. self.fci_rdm = self.molecule.get_molecular_rdm(use_fci=1) # Get explicit coefficients. self.nuclear_repulsion = self.molecular_hamiltonian.constant self.one_body = self.molecular_hamiltonian.one_body_tensor self.two_body = self.molecular_hamiltonian.two_body_tensor # Get fermion Hamiltonian. self.fermion_hamiltonian = normal_ordered( get_fermion_operator(self.molecular_hamiltonian)) # Get qubit Hamiltonian. self.qubit_hamiltonian = jordan_wigner(self.fermion_hamiltonian) # Get the sparse matrix. self.hamiltonian_matrix = get_sparse_operator( self.molecular_hamiltonian)
def test_molecular_operator_consistency(self): # Initialize H2 InteractionOperator. n_qubits = 4 filename = os.path.join(THIS_DIRECTORY, 'data', 'H2_sto-3g_singlet_0.7414') molecule = MolecularData(filename=filename) molecule_interaction = molecule.get_molecular_hamiltonian() molecule_operator = get_fermion_operator(molecule_interaction) constant = molecule_interaction.constant one_body_coefficients = molecule_interaction.one_body_tensor two_body_coefficients = molecule_interaction.two_body_tensor # Perform decomposition. eigenvalues, one_body_squares, one_body_corrections, trunc_error = ( low_rank_two_body_decomposition(two_body_coefficients)) self.assertAlmostEqual(trunc_error, 0.) # Build back operator constant and one-body components. decomposed_operator = FermionOperator((), constant) for p, q in itertools.product(range(n_qubits), repeat=2): term = ((p, 1), (q, 0)) coefficient = (one_body_coefficients[p, q] + one_body_corrections[p, q]) decomposed_operator += FermionOperator(term, coefficient) # Build back two-body component. for l in range(one_body_squares.shape[0]): one_body_operator = FermionOperator() for p, q in itertools.product(range(n_qubits), repeat=2): term = ((p, 1), (q, 0)) coefficient = one_body_squares[l, p, q] if abs(eigenvalues[l]) > 1e-6: self.assertTrue(is_hermitian(one_body_squares[l])) one_body_operator += FermionOperator(term, coefficient) decomposed_operator += eigenvalues[l] * (one_body_operator**2) # Test for consistency. difference = normal_ordered(decomposed_operator - molecule_operator) self.assertAlmostEqual(0., difference.induced_norm()) # Decompose with slightly negative operator that must use eigen molecule = MolecularData(filename=filename) molecule.two_body_integrals[0, 0, 0, 0] -= 1 eigenvalues, one_body_squares, one_body_corrections, trunc_error = ( low_rank_two_body_decomposition(two_body_coefficients)) self.assertAlmostEqual(trunc_error, 0.) # Check for property errors with self.assertRaises(TypeError): eigenvalues, one_body_squares, _, trunc_error = ( low_rank_two_body_decomposition(two_body_coefficients + 0.01j, truncation_threshold=1., final_rank=1))
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 benchmark_commutator_diagonal_coulomb_operators_2D_spinless_jellium( side_length): """Test speed of computing commutators using specialized functions. Args: side_length: The side length of the 2D jellium grid. There are side_length ** 2 qubits, and O(side_length ** 4) terms in the Hamiltonian. Returns: runtime_commutator: The time it takes to compute a commutator, after partitioning the terms and normal ordering, using the regular commutator function. runtime_diagonal_commutator: The time it takes to compute the same commutator using methods restricted to diagonal Coulomb operators. """ hamiltonian = normal_ordered( jellium_model(Grid(2, side_length, 1.), plane_wave=False)) part_a = FermionOperator.zero() part_b = FermionOperator.zero() add_to_a_or_b = 0 # add to a if 0; add to b if 1 for term, coeff in hamiltonian.terms.items(): # Partition terms in the Hamiltonian into part_a or part_b if add_to_a_or_b: part_a += FermionOperator(term, coeff) else: part_b += FermionOperator(term, coeff) add_to_a_or_b ^= 1 start = time.time() _ = normal_ordered(commutator(part_a, part_b)) end = time.time() runtime_commutator = end - start start = time.time() _ = commutator_ordered_diagonal_coulomb_with_two_body_operator( part_a, part_b) end = time.time() runtime_diagonal_commutator = end - start return runtime_commutator, runtime_diagonal_commutator
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. """ # Importing here instead of head of file to prevent circulars from openfermion.transforms.opconversions import ( reverse_jordan_wigner, 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_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_uccsd_singlet_symmetries(self): """Test that the singlet generator has the correct symmetries.""" test_orbitals = 8 test_electrons = 4 packed_amplitude_size = uccsd_singlet_paramsize( test_orbitals, test_electrons) packed_amplitudes = randn(int(packed_amplitude_size)) generator = uccsd_singlet_generator(packed_amplitudes, test_orbitals, test_electrons) # Construct symmetry operators sz = sz_operator(test_orbitals) s_squared = s_squared_operator(test_orbitals) # Check the symmetries comm_sz = normal_ordered(commutator(generator, sz)) comm_s_squared = normal_ordered(commutator(generator, s_squared)) zero = FermionOperator() self.assertEqual(comm_sz, zero) self.assertEqual(comm_s_squared, zero)
def test_split_operator_error_operator_VT_order_against_definition(self): hamiltonian = (normal_ordered(fermi_hubbard(3, 3, 1., 4.0)) - 2.3 * FermionOperator.identity()) potential_terms, kinetic_terms = ( diagonal_coulomb_potential_and_kinetic_terms_as_arrays(hamiltonian) ) potential = sum(potential_terms, FermionOperator.zero()) kinetic = sum(kinetic_terms, FermionOperator.zero()) error_operator = ( split_operator_trotter_error_operator_diagonal_two_body( hamiltonian, order='V+T')) # V-then-T ordered double commutators: [V, [T, V]] + [T, [T, V]] / 2 inner_commutator = normal_ordered(commutator(kinetic, potential)) error_operator_definition = normal_ordered( commutator(potential, inner_commutator)) error_operator_definition += normal_ordered( commutator(kinetic, inner_commutator)) / 2.0 error_operator_definition /= 12.0 self.assertEqual(error_operator, error_operator_definition)
def test_fourier_transform(self): for length in [2, 3]: grid = Grid(dimensions=1, scale=1.5, length=length) spinless_set = [True, False] geometry = [('H', (0.1, )), ('H', (0.5, ))] for spinless in spinless_set: h_plane_wave = plane_wave_hamiltonian(grid, geometry, spinless, True) h_dual_basis = plane_wave_hamiltonian(grid, geometry, spinless, False) h_plane_wave_t = fourier_transform(h_plane_wave, grid, spinless) self.assertEqual(normal_ordered(h_plane_wave_t), normal_ordered(h_dual_basis)) # Verify that all 3 are Hermitian plane_wave_operator = get_sparse_operator(h_plane_wave) dual_operator = get_sparse_operator(h_dual_basis) plane_wave_t_operator = get_sparse_operator(h_plane_wave_t) self.assertTrue(is_hermitian(plane_wave_operator)) self.assertTrue(is_hermitian(dual_operator)) self.assertTrue(is_hermitian(plane_wave_t_operator))