def test_plane_wave_hamiltonian_integration(self): length_set = [2, 3, 4] spinless_set = [True, False] length_scale = 1.1 for geometry in [[('H', (0,)), ('H', (0.8,))], [('H', (0.1,))], [('H', (0.1,))]]: for l in length_set: for spinless in spinless_set: grid = Grid(dimensions=1, scale=length_scale, length=l) h_plane_wave = plane_wave_hamiltonian( grid, geometry, spinless, True, include_constant=False) h_dual_basis = plane_wave_hamiltonian( grid, geometry, spinless, False, include_constant=False) # Test for Hermiticity plane_wave_operator = get_sparse_operator(h_plane_wave) dual_operator = get_sparse_operator(h_dual_basis) self.assertTrue(is_hermitian((plane_wave_operator))) self.assertTrue(is_hermitian(dual_operator)) jw_h_plane_wave = jordan_wigner(h_plane_wave) jw_h_dual_basis = jordan_wigner(h_dual_basis) h_plane_wave_spectrum = eigenspectrum(jw_h_plane_wave) h_dual_basis_spectrum = eigenspectrum(jw_h_dual_basis) max_diff = np.amax(h_plane_wave_spectrum - h_dual_basis_spectrum) min_diff = np.amin(h_plane_wave_spectrum - h_dual_basis_spectrum) self.assertAlmostEqual(max_diff, 0) self.assertAlmostEqual(min_diff, 0)
def test_plane_wave_period_cutoff(self): # TODO: After figuring out the correct formula for period cutoff for # dual basis, change period_cutoff to default, and change # hamiltonian_1 to a real jellium_model for real integration test. grid = Grid(dimensions=2, length=2, scale=1.0) spinless = True period_cutoff = 0. hamiltonian_1 = FermionOperator() jw_1 = jordan_wigner(hamiltonian_1) spectrum_1 = eigenspectrum(jw_1) hamiltonian_2 = jellium_model(grid, spinless, True, False, None, True, period_cutoff) jw_2 = jordan_wigner(hamiltonian_2) spectrum_2 = eigenspectrum(jw_2) max_diff = numpy.amax(numpy.absolute(spectrum_1 - spectrum_2)) self.assertGreater(max_diff, 0.) # TODO: This is only for code coverage. Remove after having real # integration test. jellium_model(grid, spinless, True, False, None, True) jellium_model(grid, spinless, False, False, None, True)
def test_model_integration(self): # Compute Hamiltonian in both momentum and position space. for length in [2, 3]: grid = Grid(dimensions=2, length=length, scale=1.0) spinless = True momentum_hamiltonian = jellium_model(grid, spinless, True) position_hamiltonian = jellium_model(grid, spinless, False) # Confirm they are Hermitian momentum_hamiltonian_operator = ( get_sparse_operator(momentum_hamiltonian)) self.assertTrue(is_hermitian(momentum_hamiltonian_operator)) position_hamiltonian_operator = ( get_sparse_operator(position_hamiltonian)) self.assertTrue(is_hermitian(position_hamiltonian_operator)) # Diagonalize and confirm the same energy. jw_momentum = jordan_wigner(momentum_hamiltonian) jw_position = jordan_wigner(position_hamiltonian) momentum_spectrum = eigenspectrum(jw_momentum) position_spectrum = eigenspectrum(jw_position) # Confirm spectra are the same. difference = numpy.amax( numpy.absolute(momentum_spectrum - position_spectrum)) self.assertAlmostEqual(difference, 0.)
def test_model_integration_with_constant(self): # Compute Hamiltonian in both momentum and position space. length_scale = 0.7 for length in [2, 3]: grid = Grid(dimensions=2, length=length, scale=length_scale) spinless = True # Include Madelung constant in the momentum but not the position # Hamiltonian. momentum_hamiltonian = jellium_model(grid, spinless, True, include_constant=True) position_hamiltonian = jellium_model(grid, spinless, False) # Confirm they are Hermitian momentum_hamiltonian_operator = ( get_sparse_operator(momentum_hamiltonian)) self.assertTrue(is_hermitian(momentum_hamiltonian_operator)) position_hamiltonian_operator = ( get_sparse_operator(position_hamiltonian)) self.assertTrue(is_hermitian(position_hamiltonian_operator)) # Diagonalize and confirm the same energy. jw_momentum = jordan_wigner(momentum_hamiltonian) jw_position = jordan_wigner(position_hamiltonian) momentum_spectrum = eigenspectrum(jw_momentum) position_spectrum = eigenspectrum(jw_position) # Confirm momentum spectrum is shifted 2.8372/length_scale higher. max_difference = numpy.amax(momentum_spectrum - position_spectrum) min_difference = numpy.amax(momentum_spectrum - position_spectrum) self.assertAlmostEqual(max_difference, 2.8372 / length_scale) self.assertAlmostEqual(min_difference, 2.8372 / length_scale)
def test_potential_integration(self): # Compute potential energy operator in momentum and position space. for length in [2, 3]: grid = Grid(dimensions=2, length=length, scale=2.) spinless = True momentum_potential = plane_wave_potential(grid, spinless) position_potential = dual_basis_potential(grid, spinless) # Confirm they are Hermitian momentum_potential_operator = ( get_sparse_operator(momentum_potential)) self.assertTrue(is_hermitian(momentum_potential_operator)) position_potential_operator = ( get_sparse_operator(position_potential)) self.assertTrue(is_hermitian(position_potential_operator)) # Diagonalize and confirm the same energy. jw_momentum = jordan_wigner(momentum_potential) jw_position = jordan_wigner(position_potential) momentum_spectrum = eigenspectrum(jw_momentum) position_spectrum = eigenspectrum(jw_position) # Confirm spectra are the same. difference = numpy.amax( numpy.absolute(momentum_spectrum - position_spectrum)) self.assertAlmostEqual(difference, 0.)
def test_interaction_operator(self): for n_orbitals, real, _ in itertools.product((1, 2, 5), (True, False), range(5)): operator = random_interaction_operator(n_orbitals, real=real) normal_ordered_operator = normal_ordered(operator) expected_qubit_operator = jordan_wigner(operator) actual_qubit_operator = jordan_wigner(normal_ordered_operator) assert expected_qubit_operator == actual_qubit_operator two_body_tensor = normal_ordered_operator.two_body_tensor n_orbitals = len(two_body_tensor) ones = numpy.ones((n_orbitals,) * 2) triu = numpy.triu(ones, 1) shape = (n_orbitals**2, 1) mask = (triu.reshape(shape) * ones.reshape(shape[::-1]) + ones.reshape(shape) * triu.reshape(shape[::-1])).reshape( (n_orbitals,) * 4) assert numpy.allclose(mask * two_body_tensor, numpy.zeros((n_orbitals,) * 4)) for term in normal_ordered_operator: order = len(term) // 2 left_term, right_term = term[:order], term[order:] assert all(i[1] == 1 for i in left_term) assert all(i[1] == 0 for i in right_term) assert left_term == tuple(sorted(left_term, reverse=True)) assert right_term == tuple(sorted(right_term, reverse=True))
def test_hermitian_conjugated_interaction_operator(self): for n_orbitals, _ in itertools.product((1, 2, 5), range(5)): operator = random_interaction_operator(n_orbitals) qubit_operator = jordan_wigner(operator) conjugate_operator = hermitian_conjugated(operator) conjugate_qubit_operator = jordan_wigner(conjugate_operator) assert hermitian_conjugated(qubit_operator) == \ conjugate_qubit_operator
def test_hermitian_conjugated_qubit_op_consistency(self): """Some consistency checks for conjugating QubitOperators.""" ferm_op = (FermionOperator('1^ 2') + FermionOperator('2 3 4') + FermionOperator('2^ 7 9 11^')) # Check that hermitian conjugation commutes with transforms self.assertEqual(jordan_wigner(hermitian_conjugated(ferm_op)), hermitian_conjugated(jordan_wigner(ferm_op))) self.assertEqual(bravyi_kitaev(hermitian_conjugated(ferm_op)), hermitian_conjugated(bravyi_kitaev(ferm_op)))
def test_plane_wave_energy_cutoff(self): grid = Grid(dimensions=1, length=5, scale=1.0) spinless = True e_cutoff = 20.0 hamiltonian_1 = jellium_model(grid, spinless, True, False) jw_1 = jordan_wigner(hamiltonian_1) spectrum_1 = eigenspectrum(jw_1) hamiltonian_2 = jellium_model(grid, spinless, True, False, e_cutoff) jw_2 = jordan_wigner(hamiltonian_2) spectrum_2 = eigenspectrum(jw_2) max_diff = numpy.amax(numpy.absolute(spectrum_1 - spectrum_2)) self.assertGreater(max_diff, 0.)
def setUp(self): geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 0.7414))] basis = 'sto-3g' multiplicity = 1 filename = os.path.join(THIS_DIRECTORY, 'data', '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_tapering_qubits_manual_input(self): """ Test taper_off_qubits function using LiH Hamiltonian. Checks different qubits inputs to remove manually. Test the lowest eigenvalue against the full Hamiltonian, and the full spectrum between them. """ hamiltonian, spectrum = lih_hamiltonian() qubit_hamiltonian = jordan_wigner(hamiltonian) stab1 = QubitOperator('Z0 Z2', -1.0) stab2 = QubitOperator('Z1 Z3', -1.0) tapered_ham_0_3 = taper_off_qubits(qubit_hamiltonian, [stab1, stab2], manual_input=True, fixed_positions=[0, 3]) tapered_ham_2_1 = taper_off_qubits(qubit_hamiltonian, [stab1, stab2], manual_input=True, fixed_positions=[2, 1]) tapered_spectrum_0_3 = eigenspectrum(tapered_ham_0_3) tapered_spectrum_2_1 = eigenspectrum(tapered_ham_2_1) self.assertAlmostEqual(spectrum[0], tapered_spectrum_0_3[0]) self.assertAlmostEqual(spectrum[0], tapered_spectrum_2_1[0]) self.assertTrue( numpy.allclose(tapered_spectrum_0_3, tapered_spectrum_2_1))
def test_plane_wave_energy_cutoff(self): geometry = [('H', (0,)), ('H', (0.8,))] grid = Grid(dimensions=1, scale=1.1, length=5) e_cutoff = 50.0 h_1 = plane_wave_hamiltonian(grid, geometry, True, True, False) jw_1 = jordan_wigner(h_1) spectrum_1 = eigenspectrum(jw_1) h_2 = plane_wave_hamiltonian(grid, geometry, True, True, False, e_cutoff) jw_2 = jordan_wigner(h_2) spectrum_2 = eigenspectrum(jw_2) max_diff = np.amax(np.absolute(spectrum_1 - spectrum_2)) self.assertGreater(max_diff, 0.)
def test_jordan_wigner_dual_basis_jellium(self): # Parameters. grid = Grid(dimensions=2, length=3, scale=1.) spinless = True # Compute fermionic Hamiltonian. Include then subtract constant. fermion_hamiltonian = dual_basis_jellium_model(grid, spinless, include_constant=True) qubit_hamiltonian = jordan_wigner(fermion_hamiltonian) qubit_hamiltonian -= QubitOperator((), 2.8372) # Compute Jordan-Wigner Hamiltonian. test_hamiltonian = jordan_wigner_dual_basis_jellium(grid, spinless) # Make sure Hamiltonians are the same. self.assertTrue(test_hamiltonian == qubit_hamiltonian) # Check number of terms. n_qubits = count_qubits(qubit_hamiltonian) if spinless: paper_n_terms = 1 - .5 * n_qubits + 1.5 * (n_qubits**2) num_nonzeros = sum( 1 for coeff in qubit_hamiltonian.terms.values() if coeff != 0.0) self.assertTrue(num_nonzeros <= paper_n_terms)
def test_identity(self): n_qubits = 5 transmed_i = reverse_jordan_wigner(self.identity, n_qubits) expected_i = FermionOperator(()) self.assertTrue(transmed_i == expected_i) retransmed_i = jordan_wigner(transmed_i) self.assertTrue(self.identity == retransmed_i)
def test_jordan_wigner(self): hamiltonian, gs_energy = lih_hamiltonian() code = jordan_wigner_code(4) qubit_hamiltonian = binary_code_transform(hamiltonian, code) self.assertAlmostEqual(gs_energy, eigenspectrum(qubit_hamiltonian)[0]) self.assertDictEqual(qubit_hamiltonian.terms, jordan_wigner(hamiltonian).terms)
def setUp(self): self.n_qubits = 5 self.majorana_operator = MajoranaOperator((1, 4, 9)) self.fermion_term = FermionOperator('1^ 2^ 3 4', -3.17) self.fermion_operator = self.fermion_term + hermitian_conjugated( self.fermion_term) self.qubit_operator = jordan_wigner(self.fermion_operator) self.interaction_operator = get_interaction_operator( self.fermion_operator)
def test_zero(self): n_qubits = 5 transmed_i = reverse_jordan_wigner(QubitOperator(), n_qubits) expected_i = FermionOperator() self.assertTrue(transmed_i == expected_i) retransmed_i = jordan_wigner(transmed_i) expected_i = QubitOperator() self.assertTrue(expected_i == retransmed_i)
def test_get_qubit_expectations(self): qubit_operator = jordan_wigner(self.hamiltonian) qubit_expectations = self.rdm.get_qubit_expectations(qubit_operator) test_energy = 0.0 for qubit_term in qubit_expectations.terms: term_coefficient = qubit_operator.terms[qubit_term] test_energy += (term_coefficient * qubit_expectations.terms[qubit_term]) self.assertLess(abs(test_energy - self.cisd_energy), EQ_TOLERANCE)
def test_z(self): pauli_z = QubitOperator(((2, 'Z'), )) transmed_z = reverse_jordan_wigner(pauli_z) expected = (FermionOperator(()) + FermionOperator( ((2, 1), (2, 0)), -2.)) self.assertTrue(transmed_z == expected) retransmed_z = jordan_wigner(transmed_z) self.assertTrue(pauli_z == retransmed_z)
def test_reduce_terms(self): """Test reduce_terms function using LiH Hamiltonian.""" hamiltonian, spectrum = lih_hamiltonian() qubit_hamiltonian = jordan_wigner(hamiltonian) stab1 = QubitOperator('Z0 Z2', -1.0) stab2 = QubitOperator('Z1 Z3', -1.0) red_eigenspectrum = eigenspectrum( reduce_number_of_terms(qubit_hamiltonian, stab1 + stab2)) self.assertAlmostEqual(spectrum[0], red_eigenspectrum[0])
def test_interaction_operator_mapping(self): # Make sure mapping of FermionOperator to InteractionOperator works. molecular_hamiltonian = get_interaction_operator( self.fermion_hamiltonian) fermion_hamiltonian = get_fermion_operator(molecular_hamiltonian) self.assertTrue(self.fermion_hamiltonian == fermion_hamiltonian) # Make sure mapping of InteractionOperator to QubitOperator works. qubit_hamiltonian = jordan_wigner(self.molecular_hamiltonian) self.assertTrue(self.qubit_hamiltonian == qubit_hamiltonian)
def test_bk_jw_majoranas(self): # Check if the Majorana operators have the same spectrum # irrespectively of the transform. a = FermionOperator(((1, 0),)) a_dag = FermionOperator(((1, 1),)) c = a + a_dag d = 1j * (a_dag - a) c_spins = [jordan_wigner(c), bravyi_kitaev(c)] d_spins = [jordan_wigner(d), bravyi_kitaev(d)] c_spectrum = [eigenspectrum(c_spins[0]), eigenspectrum(c_spins[1])] d_spectrum = [eigenspectrum(d_spins[0]), eigenspectrum(d_spins[1])] self.assertAlmostEqual( 0., numpy.amax(numpy.absolute(c_spectrum[0] - c_spectrum[1]))) self.assertAlmostEqual( 0., numpy.amax(numpy.absolute(d_spectrum[0] - d_spectrum[1])))
def test_jordan_wigner_dual_basis_hamiltonian(self): grid = Grid(dimensions=2, length=3, scale=1.) spinless_set = [True, False] geometry = [('H', (0, 0)), ('H', (0.5, 0.8))] for spinless in spinless_set: fermion_hamiltonian = plane_wave_hamiltonian( grid, geometry, spinless, False, include_constant=False) qubit_hamiltonian = jordan_wigner(fermion_hamiltonian) test_hamiltonian = jordan_wigner_dual_basis_hamiltonian( grid, geometry, spinless, include_constant=False) self.assertTrue(test_hamiltonian == qubit_hamiltonian)
def test_bk_jw_hopping_operator(self): # Check if the spectrum fits for a single hoppping operator ho = FermionOperator(((1, 1), (4, 0))) + FermionOperator( ((4, 1), (1, 0))) jw_ho = jordan_wigner(ho) bk_ho = bravyi_kitaev(ho) # Diagonalize and make sure the spectra are the same. jw_spectrum = eigenspectrum(jw_ho) bk_spectrum = eigenspectrum(bk_ho) self.assertAlmostEqual( 0., numpy.amax(numpy.absolute(jw_spectrum - bk_spectrum)))
def test_kinetic_integration(self): # Compute kinetic energy operator in both momentum and position space. grid = Grid(dimensions=2, length=2, scale=3.) spinless = False momentum_kinetic = plane_wave_kinetic(grid, spinless) position_kinetic = dual_basis_kinetic(grid, spinless) # Confirm they are Hermitian momentum_kinetic_operator = get_sparse_operator(momentum_kinetic) self.assertTrue(is_hermitian(momentum_kinetic_operator)) position_kinetic_operator = get_sparse_operator(position_kinetic) self.assertTrue(is_hermitian(position_kinetic_operator)) # Confirm spectral match and hermiticity for length in [2, 3, 4]: grid = Grid(dimensions=1, length=length, scale=2.1) spinless = False momentum_kinetic = plane_wave_kinetic(grid, spinless) position_kinetic = dual_basis_kinetic(grid, spinless) # Confirm they are Hermitian momentum_kinetic_operator = get_sparse_operator(momentum_kinetic) self.assertTrue(is_hermitian(momentum_kinetic_operator)) position_kinetic_operator = get_sparse_operator(position_kinetic) self.assertTrue(is_hermitian(position_kinetic_operator)) # Diagonalize and confirm the same energy. jw_momentum = jordan_wigner(momentum_kinetic) jw_position = jordan_wigner(position_kinetic) momentum_spectrum = eigenspectrum(jw_momentum, 2 * length) position_spectrum = eigenspectrum(jw_position, 2 * length) # Confirm spectra are the same. difference = numpy.amax( numpy.absolute(momentum_spectrum - position_spectrum)) self.assertAlmostEqual(difference, 0.)
def test_reduce_terms_manual_input(self): """Test reduce_terms function using LiH Hamiltonian.""" hamiltonian, spectrum = lih_hamiltonian() qubit_hamiltonian = jordan_wigner(hamiltonian) stab1 = QubitOperator('Z0 Z2', -1.0) stab2 = QubitOperator('Z1 Z3', -1.0) red_eigenspectrum = eigenspectrum( reduce_number_of_terms(qubit_hamiltonian, [stab1, stab2], manual_input=True, fixed_positions=[0, 1])) self.assertAlmostEqual(spectrum[0], red_eigenspectrum[0])
def test_bk_jw_number_operator(self): # Check if number operator has the same spectrum in both # BK and JW representations n = number_operator(1, 0) jw_n = jordan_wigner(n) bk_n = bravyi_kitaev(n) # Diagonalize and make sure the spectra are the same. jw_spectrum = eigenspectrum(jw_n) bk_spectrum = eigenspectrum(bk_n) self.assertAlmostEqual( 0., numpy.amax(numpy.absolute(jw_spectrum - bk_spectrum)))
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_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_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))