def test_fci_energy(): filename = os.path.join(DATA_DIRECTORY, "H2_sto-3g_singlet_0.7414.hdf5") molecule = MolecularData(filename=filename) reduced_ham = make_reduced_hamiltonian(molecule.get_molecular_hamiltonian(), molecule.n_electrons) numpy_ham = get_number_preserving_sparse_operator( get_fermion_operator(reduced_ham), molecule.n_qubits, num_electrons=molecule.n_electrons, spin_preserving=True) w, _ = numpy.linalg.eigh(numpy_ham.toarray()) assert numpy.isclose(molecule.fci_energy, w[0]) 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) numpy_ham = get_number_preserving_sparse_operator( get_fermion_operator(reduced_ham), molecule.n_qubits, num_electrons=molecule.n_electrons, spin_preserving=True) w, _ = numpy.linalg.eigh(numpy_ham.toarray()) assert numpy.isclose(molecule.fci_energy, w[0])
def lih_hamiltonian(): """ Generate test Hamiltonian from LiH. Args: None Return: hamiltonian: FermionicOperator spectrum: List of energies. """ geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))] active_space_start = 1 active_space_stop = 3 molecule = MolecularData(geometry, 'sto-3g', 1, description="1.45") molecule.load() molecular_hamiltonian = molecule.get_molecular_hamiltonian( occupied_indices=range(active_space_start), active_indices=range(active_space_start, active_space_stop)) hamiltonian = get_fermion_operator(molecular_hamiltonian) spectrum = eigenspectrum(hamiltonian) return hamiltonian, spectrum
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_mrd_return_type(): filename = os.path.join(DATA_DIRECTORY, "H2_sto-3g_singlet_0.7414.hdf5") molecule = MolecularData(filename=filename) reduced_ham = make_reduced_hamiltonian(molecule.get_molecular_hamiltonian(), molecule.n_electrons) assert isinstance(reduced_ham, InteractionOperator)
def test_consistency(self): """Test consistency with JW for FermionOperators.""" # Random interaction operator n_qubits = 5 iop = random_interaction_operator(n_qubits, real=False) op1 = jordan_wigner(iop) op2 = jordan_wigner(get_fermion_operator(iop)) self.assertEqual(op1, op2) # Interaction operator from molecule geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))] basis = 'sto-3g' multiplicity = 1 filename = os.path.join(DATA_DIRECTORY, 'H1-Li1_sto-3g_singlet_1.45') molecule = MolecularData(geometry, basis, multiplicity, filename=filename) molecule.load() iop = molecule.get_molecular_hamiltonian() op1 = jordan_wigner(iop) op2 = jordan_wigner(get_fermion_operator(iop)) self.assertEqual(op1, op2)
def test_constant_one_body(): filename = os.path.join(DATA_DIRECTORY, "H2_sto-3g_singlet_0.7414.hdf5") molecule = MolecularData(filename=filename) reduced_ham = make_reduced_hamiltonian(molecule.get_molecular_hamiltonian(), molecule.n_electrons) assert numpy.isclose(reduced_ham.constant, molecule.nuclear_repulsion) assert numpy.allclose(reduced_ham.one_body_tensor, 0)
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_one_body_square_decomposition(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() get_fermion_operator(molecule_interaction) two_body_coefficients = molecule_interaction.two_body_tensor # Decompose. eigenvalues, one_body_squares, _, _ = (low_rank_two_body_decomposition( two_body_coefficients, truncation_threshold=0)) rank = eigenvalues.size for l in range(rank): 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] one_body_operator += FermionOperator(term, coefficient) one_body_squared = one_body_operator**2 # Get the squared one-body operator via one-body decomposition. if abs(eigenvalues[l]) < 1e-6: with self.assertRaises(ValueError): prepare_one_body_squared_evolution(one_body_squares[l]) continue else: density_density_matrix, basis_transformation_matrix = ( prepare_one_body_squared_evolution(one_body_squares[l])) two_body_operator = FermionOperator() for p, q in itertools.product(range(n_qubits), repeat=2): term = ((p, 1), (p, 0), (q, 1), (q, 0)) coefficient = density_density_matrix[p, q] two_body_operator += FermionOperator(term, coefficient) # Confirm that the rotations diagonalize the one-body squares. hopefully_diagonal = basis_transformation_matrix.dot( numpy.dot( one_body_squares[l], numpy.transpose( numpy.conjugate(basis_transformation_matrix)))) diagonal = numpy.diag(hopefully_diagonal) difference = hopefully_diagonal - numpy.diag(diagonal) self.assertAlmostEqual(0., numpy.amax(numpy.absolute(difference))) density_density_alternative = numpy.outer(diagonal, diagonal) difference = density_density_alternative - density_density_matrix self.assertAlmostEqual(0., numpy.amax(numpy.absolute(difference))) # Test spectra. one_body_squared_spectrum = eigenspectrum(one_body_squared) two_body_spectrum = eigenspectrum(two_body_operator) difference = two_body_spectrum - one_body_squared_spectrum self.assertAlmostEqual(0., numpy.amax(numpy.absolute(difference)))
def lih_hamiltonian(): geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))] active_space_start = 1 active_space_stop = 3 molecule = MolecularData(geometry, 'sto-3g', 1, description="1.45") molecule.load() molecular_hamiltonian = molecule.get_molecular_hamiltonian( occupied_indices=range(active_space_start), active_indices=range(active_space_start, active_space_stop)) hamiltonian = get_fermion_operator(molecular_hamiltonian) ground_state_energy = eigenspectrum(hamiltonian)[0] return hamiltonian, ground_state_energy
def test_h2_rpa(): filename = os.path.join(DATA_DIRECTORY, "H2_sto-3g_singlet_0.7414.hdf5") molecule = MolecularData(filename=filename) reduced_ham = make_reduced_hamiltonian( molecule.get_molecular_hamiltonian(), molecule.n_electrons) hf_opdm = np.diag([1] * molecule.n_electrons + [0] * (molecule.n_qubits - molecule.n_electrons)) hf_tpdm = 2 * wedge(hf_opdm, hf_opdm, (1, 1), (1, 1)) pos_spectrum, xy_eigvects, basis = singlet_erpa( hf_tpdm, reduced_ham.two_body_tensor) assert np.isclose(pos_spectrum, 0.92926444) # pyscf-rpa value assert isinstance(xy_eigvects, np.ndarray) assert isinstance(basis, dict)
def LiH_sto3g(): """ Generates the Hamiltonian for LiH in the STO-3G basis, at a distance of 1.45 A. """ geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))] molecule = MolecularData(geometry, 'sto-3g', 1, description="1.45") molecule.load() molecular_hamiltonian = molecule.get_molecular_hamiltonian() hamiltonian = get_fermion_operator(molecular_hamiltonian) num_electrons = molecule.n_electrons num_orbitals = 2 * molecule.n_orbitals return hamiltonian, num_orbitals, num_electrons
def setUp(self): # Set up molecule. 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') molecule = MolecularData(geometry, basis, multiplicity, filename=filename) molecule.load() self.n_fermions = molecule.n_electrons self.n_orbitals = molecule.n_qubits # Get molecular Hamiltonian. molecular_hamiltonian = molecule.get_molecular_hamiltonian() self.fermion_hamiltonian = get_fermion_operator(molecular_hamiltonian)
def setUp(self): # Setup. 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') molecule = MolecularData(geometry, basis, multiplicity, filename=filename) molecule.load() self.n_fermions = molecule.n_electrons self.n_orbitals = molecule.n_qubits # Get molecular Hamiltonian. self.molecular_hamiltonian = molecule.get_molecular_hamiltonian() self.fci_rdm = molecule.get_molecular_rdm(use_fci=1)
class InteractionRDMTest(unittest.TestCase): 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() self.cisd_energy = self.molecule.cisd_energy self.rdm = self.molecule.get_molecular_rdm() self.hamiltonian = self.molecule.get_molecular_hamiltonian() 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_get_qubit_expectations_nonmolecular_term(self): with self.assertRaises(InteractionRDMError): self.rdm.get_qubit_expectations(QubitOperator('X1 X2 X3 X4 Y6')) def test_get_qubit_expectations_through_expectation_method(self): qubit_operator = jordan_wigner(self.hamiltonian) test_energy = self.rdm.expectation(qubit_operator) self.assertLess(abs(test_energy - self.cisd_energy), EQ_TOLERANCE) def test_get_molecular_operator_expectation(self): expectation = self.rdm.expectation(self.hamiltonian) self.assertAlmostEqual(expectation, self.cisd_energy, places=7) def test_expectation_bad_type(self): with self.assertRaises(InteractionRDMError): self.rdm.expectation(12) def test_addition(self): rdm2 = self.rdm + self.rdm self.assertTrue( numpy.array_equal(rdm2.one_body_tensor, rdm2.n_body_tensors[(1, 0)])) self.assertTrue( numpy.array_equal(rdm2.two_body_tensor, rdm2.n_body_tensors[(1, 1, 0, 0)])) def test_rdm_setters(self): temp_rdm = self.molecule.get_molecular_rdm() one_body_tensor_test = numpy.eye(4) temp_rdm.one_body_tensor = one_body_tensor_test self.assertTrue( numpy.array_equal(temp_rdm.n_body_tensors[(1, 0)], one_body_tensor_test)) two_body_tensor_test = numpy.zeros([4, 4, 4, 4]) temp_rdm.two_body_tensor = two_body_tensor_test self.assertTrue( numpy.array_equal(temp_rdm.n_body_tensors[(1, 1, 0, 0)], two_body_tensor_test))
def test_rank_reduction(self): # Initialize H2 InteractionOperator. n_qubits = 4 n_orbitals = 2 filename = os.path.join(THIS_DIRECTORY, 'data', 'H2_sto-3g_singlet_0.7414') molecule = MolecularData(filename=filename) molecule_interaction = molecule.get_molecular_hamiltonian() fermion_operator = get_fermion_operator(molecule_interaction) constant = molecule_interaction.constant two_body_coefficients = molecule_interaction.two_body_tensor # Rank reduce with threshold. errors = [] for truncation_threshold in [1., 0.1, 0.01, 0.001]: # Decompose with threshold. (test_eigenvalues, one_body_squares, one_body_correction, trunc_error) = low_rank_two_body_decomposition( two_body_coefficients, truncation_threshold=truncation_threshold) # Make sure error is below truncation specification. self.assertTrue(trunc_error > 0.) self.assertTrue(trunc_error < truncation_threshold) self.assertTrue(len(test_eigenvalues) < n_orbitals**2) self.assertTrue(len(one_body_squares) == len(test_eigenvalues)) # Build back operator constant and one-body components. decomposed_operator = FermionOperator((), constant) one_body_coefficients = (molecule_interaction.one_body_tensor + one_body_correction) for p, q in itertools.product(range(n_qubits), repeat=2): term = ((p, 1), (q, 0)) coefficient = one_body_coefficients[p, q] decomposed_operator += FermionOperator(term, coefficient) # Build back two-body component. for l in range(len(test_eigenvalues)): 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] one_body_operator += FermionOperator(term, coefficient) decomposed_operator += (test_eigenvalues[l] * one_body_operator**2) # Test for consistency. difference = normal_ordered(decomposed_operator - fermion_operator) errors += [difference.induced_norm()] self.assertTrue(errors[-1] <= trunc_error) self.assertTrue(errors[3] <= errors[2] <= errors[1] <= errors[0]) # Rank reduce by imposing final rank. errors = [] for final_rank in [1, 2, 3, 4]: # Decompose with threshold. (test_eigenvalues, one_body_squares, one_body_correction, trunc_error) = low_rank_two_body_decomposition( two_body_coefficients, final_rank=final_rank) # Make sure error is below truncation specification. self.assertTrue(len(test_eigenvalues) == final_rank) # Build back operator constant and one-body components. decomposed_operator = FermionOperator((), constant) one_body_coefficients = (molecule_interaction.one_body_tensor + one_body_correction) for p, q in itertools.product(range(n_qubits), repeat=2): term = ((p, 1), (q, 0)) coefficient = one_body_coefficients[p, q] decomposed_operator += FermionOperator(term, coefficient) # Build back two-body component. for l in range(final_rank): 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] one_body_operator += FermionOperator(term, coefficient) decomposed_operator += (test_eigenvalues[l] * one_body_operator**2) # Test for consistency. difference = normal_ordered(decomposed_operator - fermion_operator) errors += [difference.induced_norm()] self.assertTrue(errors[3] <= errors[2] <= errors[1] <= errors[0])
class bravyi_kitaev_fastTransformTest(unittest.TestCase): 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_bad_input(self): with self.assertRaises(TypeError): bksf.bravyi_kitaev_fast(FermionOperator()) def test_bravyi_kitaev_fast_edgeoperator_Bi(self): # checking the edge operators edge_matrix = numpy.triu(numpy.ones((4, 4))) edge_matrix_indices = numpy.array( numpy.nonzero( numpy.triu(edge_matrix) - numpy.diag(numpy.diag(edge_matrix)))) correct_operators_b0 = ((0, 'Z'), (1, 'Z'), (2, 'Z')) correct_operators_b1 = ((0, 'Z'), (3, 'Z'), (4, 'Z')) correct_operators_b2 = ((1, 'Z'), (3, 'Z'), (5, 'Z')) correct_operators_b3 = ((2, 'Z'), (4, 'Z'), (5, 'Z')) qterm_b0 = QubitOperator(correct_operators_b0, 1) qterm_b1 = QubitOperator(correct_operators_b1, 1) qterm_b2 = QubitOperator(correct_operators_b2, 1) qterm_b3 = QubitOperator(correct_operators_b3, 1) self.assertTrue( qterm_b0 == bksf.edge_operator_b(edge_matrix_indices, 0)) self.assertTrue( qterm_b1 == bksf.edge_operator_b(edge_matrix_indices, 1)) self.assertTrue( qterm_b2 == bksf.edge_operator_b(edge_matrix_indices, 2)) self.assertTrue( qterm_b3 == bksf.edge_operator_b(edge_matrix_indices, 3)) def test_bravyi_kitaev_fast_edgeoperator_Aij(self): # checking the edge operators edge_matrix = numpy.triu(numpy.ones((4, 4))) edge_matrix_indices = numpy.array( numpy.nonzero( numpy.triu(edge_matrix) - numpy.diag(numpy.diag(edge_matrix)))) correct_operators_a01 = ((0, 'X'), ) correct_operators_a02 = ((0, 'Z'), (1, 'X')) correct_operators_a03 = ((0, 'Z'), (1, 'Z'), (2, 'X')) correct_operators_a12 = ((0, 'Z'), (1, 'Z'), (3, 'X')) correct_operators_a13 = ((0, 'Z'), (2, 'Z'), (3, 'Z'), (4, 'X')) correct_operators_a23 = ((1, 'Z'), (2, 'Z'), (3, 'Z'), (4, 'Z'), (5, 'X')) qterm_a01 = QubitOperator(correct_operators_a01, 1) qterm_a02 = QubitOperator(correct_operators_a02, 1) qterm_a03 = QubitOperator(correct_operators_a03, 1) qterm_a12 = QubitOperator(correct_operators_a12, 1) qterm_a13 = QubitOperator(correct_operators_a13, 1) qterm_a23 = QubitOperator(correct_operators_a23, 1) self.assertTrue( qterm_a01 == bksf.edge_operator_aij(edge_matrix_indices, 0, 1)) self.assertTrue( qterm_a02 == bksf.edge_operator_aij(edge_matrix_indices, 0, 2)) self.assertTrue( qterm_a03 == bksf.edge_operator_aij(edge_matrix_indices, 0, 3)) self.assertTrue( qterm_a12 == bksf.edge_operator_aij(edge_matrix_indices, 1, 2)) self.assertTrue( qterm_a13 == bksf.edge_operator_aij(edge_matrix_indices, 1, 3)) self.assertTrue( qterm_a23 == bksf.edge_operator_aij(edge_matrix_indices, 2, 3)) def test_bravyi_kitaev_fast_jw_number_operator(self): # bksf algorithm allows for even number of particles. So, compare the # spectrum of number operator from jordan-wigner and bksf algorithm # to make sure half of the jordan-wigner number operator spectrum # can be found in bksf number operator spectrum. bravyi_kitaev_fast_n = bksf.number_operator(self.molecular_hamiltonian) jw_n = QubitOperator() n_qubits = count_qubits(self.molecular_hamiltonian) for i in range(n_qubits): jw_n += jordan_wigner_one_body(i, i) jw_eig_spec = eigenspectrum(jw_n) bravyi_kitaev_fast_eig_spec = eigenspectrum(bravyi_kitaev_fast_n) evensector = 0 for i in range(numpy.size(jw_eig_spec)): if bool( numpy.size( numpy.where( jw_eig_spec[i] == bravyi_kitaev_fast_eig_spec))): evensector += 1 self.assertEqual(evensector, 2**(n_qubits - 1)) def test_bravyi_kitaev_fast_jw_hamiltonian(self): # make sure half of the jordan-wigner Hamiltonian eigenspectrum can # be found in bksf Hamiltonian eigenspectrum. n_qubits = count_qubits(self.molecular_hamiltonian) bravyi_kitaev_fast_H = bksf.bravyi_kitaev_fast( self.molecular_hamiltonian) jw_H = jordan_wigner(self.molecular_hamiltonian) bravyi_kitaev_fast_H_eig = eigenspectrum(bravyi_kitaev_fast_H) jw_H_eig = eigenspectrum(jw_H) bravyi_kitaev_fast_H_eig = bravyi_kitaev_fast_H_eig.round(5) jw_H_eig = jw_H_eig.round(5) evensector = 0 for i in range(numpy.size(jw_H_eig)): if bool( numpy.size( numpy.where(jw_H_eig[i] == bravyi_kitaev_fast_H_eig))): evensector += 1 self.assertEqual(evensector, 2**(n_qubits - 1)) def test_bravyi_kitaev_fast_generate_fermions(self): n_qubits = count_qubits(self.molecular_hamiltonian) # test for generating two fermions edge_matrix = bksf.bravyi_kitaev_fast_edge_matrix( self.molecular_hamiltonian) edge_matrix_indices = numpy.array( numpy.nonzero( numpy.triu(edge_matrix) - numpy.diag(numpy.diag(edge_matrix)))) fermion_generation_operator = bksf.generate_fermions( edge_matrix_indices, 2, 3) fermion_generation_sp_matrix = get_sparse_operator( fermion_generation_operator) fermion_generation_matrix = fermion_generation_sp_matrix.toarray() bksf_vacuum_state_operator = bksf.vacuum_operator(edge_matrix_indices) bksf_vacuum_state_sp_matrix = get_sparse_operator( bksf_vacuum_state_operator) bksf_vacuum_state_matrix = bksf_vacuum_state_sp_matrix.toarray() vacuum_state = numpy.zeros((2**(n_qubits), 1)) vacuum_state[0] = 1. bksf_vacuum_state = numpy.dot(bksf_vacuum_state_matrix, vacuum_state) two_fermion_state = numpy.dot(fermion_generation_matrix, bksf_vacuum_state) # using total number operator to check the number of fermions generated tot_number_operator = bksf.number_operator(self.molecular_hamiltonian) number_operator_sp_matrix = get_sparse_operator(tot_number_operator) number_operator_matrix = number_operator_sp_matrix.toarray() tot_fermions = numpy.dot( two_fermion_state.conjugate().T, numpy.dot(number_operator_matrix, two_fermion_state)) # checking the occupation number of site 2 and 3 number_operator_2 = bksf.number_operator(self.molecular_hamiltonian, 2) number_operator_3 = bksf.number_operator(self.molecular_hamiltonian, 3) number_operator_23 = number_operator_2 + number_operator_3 number_operator_23_sp_matrix = get_sparse_operator(number_operator_23) number_operator_23_matrix = number_operator_23_sp_matrix.toarray() tot_23_fermions = numpy.dot( two_fermion_state.conjugate().T, numpy.dot(number_operator_23_matrix, two_fermion_state)) self.assertTrue(2.0 - float(tot_fermions.real) < 1e-13) self.assertTrue(2.0 - float(tot_23_fermions.real) < 1e-13) def test_bravyi_kitaev_fast_excitation_terms(self): # Testing on-site and excitation terms in Hamiltonian constant = 0 one_body = numpy.array([[1, 2, 0, 3], [2, 1, 2, 0], [0, 2, 1, 2.5], [3, 0, 2.5, 1]]) # No Coloumb interaction two_body = numpy.zeros((4, 4, 4, 4)) molecular_hamiltonian = InteractionOperator(constant, one_body, two_body) n_qubits = count_qubits(molecular_hamiltonian) # comparing the eigenspectrum of Hamiltonian bravyi_kitaev_fast_H = bksf.bravyi_kitaev_fast(molecular_hamiltonian) jw_H = jordan_wigner(molecular_hamiltonian) bravyi_kitaev_fast_H_eig = eigenspectrum(bravyi_kitaev_fast_H) jw_H_eig = eigenspectrum(jw_H) bravyi_kitaev_fast_H_eig = bravyi_kitaev_fast_H_eig.round(5) jw_H_eig = jw_H_eig.round(5) evensector_H = 0 for i in range(numpy.size(jw_H_eig)): if bool( numpy.size( numpy.where(jw_H_eig[i] == bravyi_kitaev_fast_H_eig))): evensector_H += 1 # comparing eigenspectrum of number operator bravyi_kitaev_fast_n = bksf.number_operator(molecular_hamiltonian) jw_n = QubitOperator() n_qubits = count_qubits(molecular_hamiltonian) for i in range(n_qubits): jw_n += jordan_wigner_one_body(i, i) jw_eig_spec = eigenspectrum(jw_n) bravyi_kitaev_fast_eig_spec = eigenspectrum(bravyi_kitaev_fast_n) evensector_n = 0 for i in range(numpy.size(jw_eig_spec)): if bool( numpy.size( numpy.where( jw_eig_spec[i] == bravyi_kitaev_fast_eig_spec))): evensector_n += 1 self.assertEqual(evensector_H, 2**(n_qubits - 1)) self.assertEqual(evensector_n, 2**(n_qubits - 1)) def test_bravyi_kitaev_fast_number_excitation_operator(self): # using hydrogen Hamiltonian and introducing some number operator terms constant = 0 one_body = numpy.zeros((4, 4)) one_body[(0, 0)] = .4 one_body[(1, 1)] = .5 one_body[(2, 2)] = .6 one_body[(3, 3)] = .7 two_body = self.molecular_hamiltonian.two_body_tensor # initiating number operator terms for all the possible cases two_body[(1, 2, 3, 1)] = 0.1 two_body[(1, 3, 2, 1)] = 0.1 two_body[(1, 2, 1, 3)] = 0.15 two_body[(3, 1, 2, 1)] = 0.15 two_body[(0, 2, 2, 1)] = 0.09 two_body[(1, 2, 2, 0)] = 0.09 two_body[(1, 2, 3, 2)] = 0.11 two_body[(2, 3, 2, 1)] = 0.11 two_body[(2, 2, 2, 2)] = 0.1 molecular_hamiltonian = InteractionOperator(constant, one_body, two_body) # comparing the eigenspectrum of Hamiltonian n_qubits = count_qubits(molecular_hamiltonian) bravyi_kitaev_fast_H = bksf.bravyi_kitaev_fast(molecular_hamiltonian) jw_H = jordan_wigner(molecular_hamiltonian) bravyi_kitaev_fast_H_eig = eigenspectrum(bravyi_kitaev_fast_H) jw_H_eig = eigenspectrum(jw_H) bravyi_kitaev_fast_H_eig = bravyi_kitaev_fast_H_eig.round(5) jw_H_eig = jw_H_eig.round(5) evensector_H = 0 for i in range(numpy.size(jw_H_eig)): if bool( numpy.size( numpy.where(jw_H_eig[i] == bravyi_kitaev_fast_H_eig))): evensector_H += 1 # comparing eigenspectrum of number operator bravyi_kitaev_fast_n = bksf.number_operator(molecular_hamiltonian) jw_n = QubitOperator() n_qubits = count_qubits(molecular_hamiltonian) for i in range(n_qubits): jw_n += jordan_wigner_one_body(i, i) jw_eig_spec = eigenspectrum(jw_n) bravyi_kitaev_fast_eig_spec = eigenspectrum(bravyi_kitaev_fast_n) evensector_n = 0 for i in range(numpy.size(jw_eig_spec)): if bool( numpy.size( numpy.where( jw_eig_spec[i] == bravyi_kitaev_fast_eig_spec))): evensector_n += 1 self.assertEqual(evensector_H, 2**(n_qubits - 1)) self.assertEqual(evensector_n, 2**(n_qubits - 1))
class HydrogenIntegrationTest(unittest.TestCase): 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_integral_data(self): # Initialize coefficients given in arXiv 1208.5986: g0 = 0.71375 g1 = -1.2525 g2 = -0.47593 g3 = 0.67449 / 2. g4 = 0.69740 / 2. g5 = 0.66347 / 2. g6 = 0.18129 / 2. # Check the integrals in the test data. self.assertAlmostEqual(self.nuclear_repulsion, g0, places=4) self.assertAlmostEqual(self.one_body[0, 0], g1, places=4) self.assertAlmostEqual(self.one_body[1, 1], g1, places=4) self.assertAlmostEqual(self.one_body[2, 2], g2, places=4) self.assertAlmostEqual(self.one_body[3, 3], g2, places=4) self.assertAlmostEqual(self.two_body[0, 1, 1, 0], g3, places=4) self.assertAlmostEqual(self.two_body[1, 0, 0, 1], g3, places=4) self.assertAlmostEqual(self.two_body[2, 3, 3, 2], g4, places=4) self.assertAlmostEqual(self.two_body[3, 2, 2, 3], g4, places=4) self.assertAlmostEqual(self.two_body[0, 2, 2, 0], g5, places=4) self.assertAlmostEqual(self.two_body[0, 3, 3, 0], g5, places=4) self.assertAlmostEqual(self.two_body[1, 2, 2, 1], g5, places=4) self.assertAlmostEqual(self.two_body[1, 3, 3, 1], g5, places=4) self.assertAlmostEqual(self.two_body[2, 0, 0, 2], g5, places=4) self.assertAlmostEqual(self.two_body[3, 0, 0, 3], g5, places=4) self.assertAlmostEqual(self.two_body[2, 1, 1, 2], g5, places=4) self.assertAlmostEqual(self.two_body[3, 1, 1, 3], g5, places=4) self.assertAlmostEqual(self.two_body[0, 2, 0, 2], g6, places=4) self.assertAlmostEqual(self.two_body[1, 3, 1, 3], g6, places=4) self.assertAlmostEqual(self.two_body[2, 1, 3, 0], g6, places=4) self.assertAlmostEqual(self.two_body[2, 3, 1, 0], g6, places=4) self.assertAlmostEqual(self.two_body[0, 3, 1, 2], g6, places=4) self.assertAlmostEqual(self.two_body[0, 1, 3, 2], g6, places=4) def test_qubit_operator(self): # Below are qubit term coefficients, also from arXiv 1208.5986: f1 = 0.1712 f2 = -0.2228 f3 = 0.1686 f4 = 0.1205 f5 = 0.1659 f6 = 0.1743 f7 = 0.04532 # Test the local Hamiltonian terms. self.assertAlmostEqual(self.qubit_hamiltonian.terms[((0, 'Z'), )], f1, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((1, 'Z'), )], f1, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((2, 'Z'), )], f2, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((3, 'Z'), )], f2, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((0, 'Z'), (1, 'Z'))], f3, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((0, 'Z'), (2, 'Z'))], f4, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((1, 'Z'), (3, 'Z'))], f4, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((1, 'Z'), (2, 'Z'))], f5, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((0, 'Z'), (3, 'Z'))], f5, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((2, 'Z'), (3, 'Z'))], f6, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((0, 'Y'), (1, 'Y'), (2, 'X'), (3, 'X'))], -f7, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((0, 'X'), (1, 'X'), (2, 'Y'), (3, 'Y'))], -f7, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((0, 'X'), (1, 'Y'), (2, 'Y'), (3, 'X'))], f7, places=4) self.assertAlmostEqual(self.qubit_hamiltonian.terms[((0, 'Y'), (1, 'X'), (2, 'X'), (3, 'Y'))], f7, places=4) def test_reverse_jordan_wigner(self): fermion_hamiltonian = reverse_jordan_wigner(self.qubit_hamiltonian) fermion_hamiltonian = normal_ordered(fermion_hamiltonian) self.assertTrue(self.fermion_hamiltonian == fermion_hamiltonian) 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_rdm_numerically(self): # Test energy of RDM. fci_rdm_energy = self.nuclear_repulsion fci_rdm_energy += numpy.sum(self.fci_rdm.one_body_tensor * self.molecular_hamiltonian.one_body_tensor) fci_rdm_energy += numpy.sum(self.fci_rdm.two_body_tensor * self.molecular_hamiltonian.two_body_tensor) self.assertAlmostEqual(fci_rdm_energy, self.molecule.fci_energy) # Confirm expectation on qubit Hamiltonian using reverse JW matches. qubit_rdm = self.fci_rdm.get_qubit_expectations(self.qubit_hamiltonian) qubit_energy = 0.0 for term, expectation in qubit_rdm.terms.items(): qubit_energy += expectation * self.qubit_hamiltonian.terms[term] self.assertAlmostEqual(qubit_energy, self.molecule.fci_energy) # Confirm fermionic RDMs can be built from measured qubit RDMs new_fermi_rdm = get_interaction_rdm(qubit_rdm) new_fermi_rdm.expectation(self.molecular_hamiltonian) self.assertAlmostEqual(fci_rdm_energy, self.molecule.fci_energy) def test_sparse_numerically(self): # Check FCI energy. energy, wavefunction = get_ground_state(self.hamiltonian_matrix) self.assertAlmostEqual(energy, self.molecule.fci_energy) expected_energy = expectation(self.hamiltonian_matrix, wavefunction) self.assertAlmostEqual(expected_energy, energy) # Make sure you can reproduce Hartree energy. hf_state = jw_hartree_fock_state(self.molecule.n_electrons, count_qubits(self.qubit_hamiltonian)) hf_density = get_density_matrix([hf_state], [1.]) # Make sure you can reproduce Hartree-Fock energy. hf_state = jw_hartree_fock_state(self.molecule.n_electrons, count_qubits(self.qubit_hamiltonian)) hf_density = get_density_matrix([hf_state], [1.]) expected_hf_density_energy = expectation(self.hamiltonian_matrix, hf_density) expected_hf_energy = expectation(self.hamiltonian_matrix, hf_state) self.assertAlmostEqual(expected_hf_energy, self.molecule.hf_energy) self.assertAlmostEqual(expected_hf_density_energy, self.molecule.hf_energy)
class LiHIntegrationTest(unittest.TestCase): def setUp(self): # Set up molecule. geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., 1.45))] basis = 'sto-3g' multiplicity = 1 filename = os.path.join(THIS_DIRECTORY, 'data', 'H1-Li1_sto-3g_singlet_1.45') self.molecule = MolecularData(geometry, basis, multiplicity, filename=filename) self.molecule.load() # Get molecular Hamiltonian self.molecular_hamiltonian = self.molecule.get_molecular_hamiltonian() self.molecular_hamiltonian_no_core = ( self.molecule.get_molecular_hamiltonian( occupied_indices=[0], active_indices=range(1, self.molecule.n_orbitals))) # 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 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 matrix form. self.hamiltonian_matrix = get_sparse_operator( self.molecular_hamiltonian) self.hamiltonian_matrix_no_core = get_sparse_operator( self.molecular_hamiltonian_no_core) def test_all(self): # Test reverse Jordan-Wigner. fermion_hamiltonian = reverse_jordan_wigner(self.qubit_hamiltonian) fermion_hamiltonian = normal_ordered(fermion_hamiltonian) self.assertTrue(self.fermion_hamiltonian == fermion_hamiltonian) # Test mapping to interaction operator. fermion_hamiltonian = get_fermion_operator(self.molecular_hamiltonian) fermion_hamiltonian = normal_ordered(fermion_hamiltonian) self.assertTrue(self.fermion_hamiltonian == fermion_hamiltonian) # Test RDM energy. fci_rdm_energy = self.nuclear_repulsion fci_rdm_energy += numpy.sum(self.fci_rdm.one_body_tensor * self.one_body) fci_rdm_energy += numpy.sum(self.fci_rdm.two_body_tensor * self.two_body) self.assertAlmostEqual(fci_rdm_energy, self.molecule.fci_energy) # Confirm expectation on qubit Hamiltonian using reverse JW matches. qubit_rdm = self.fci_rdm.get_qubit_expectations(self.qubit_hamiltonian) qubit_energy = 0.0 for term, coefficient in qubit_rdm.terms.items(): qubit_energy += coefficient * self.qubit_hamiltonian.terms[term] self.assertAlmostEqual(qubit_energy, self.molecule.fci_energy) # Confirm fermionic RDMs can be built from measured qubit RDMs. new_fermi_rdm = get_interaction_rdm(qubit_rdm) new_fermi_rdm.expectation(self.molecular_hamiltonian) self.assertAlmostEqual(fci_rdm_energy, self.molecule.fci_energy) # Test sparse matrices. energy, wavefunction = get_ground_state(self.hamiltonian_matrix) self.assertAlmostEqual(energy, self.molecule.fci_energy) expected_energy = expectation(self.hamiltonian_matrix, wavefunction) self.assertAlmostEqual(expected_energy, energy) # Make sure you can reproduce Hartree-Fock energy. hf_state = jw_hartree_fock_state(self.molecule.n_electrons, count_qubits(self.qubit_hamiltonian)) hf_density = get_density_matrix([hf_state], [1.]) expected_hf_density_energy = expectation(self.hamiltonian_matrix, hf_density) expected_hf_energy = expectation(self.hamiltonian_matrix, hf_state) self.assertAlmostEqual(expected_hf_energy, self.molecule.hf_energy) self.assertAlmostEqual(expected_hf_density_energy, self.molecule.hf_energy) # Check that frozen core result matches frozen core FCI from psi4. # Recore frozen core result from external calculation. self.frozen_core_fci_energy = -7.8807607374168 no_core_fci_energy = numpy.linalg.eigh( self.hamiltonian_matrix_no_core.toarray())[0][0] self.assertAlmostEqual(no_core_fci_energy, self.frozen_core_fci_energy) # Check that the freeze_orbitals function has the same effect as the # as the occupied_indices option of get_molecular_hamiltonian. frozen_hamiltonian = freeze_orbitals( get_fermion_operator(self.molecular_hamiltonian), [0, 1]) self.assertTrue(frozen_hamiltonian == get_fermion_operator( self.molecular_hamiltonian_no_core))
class UnitaryCC(unittest.TestCase): def test_uccsd_anti_hermitian(self): """Test operators are anti-Hermitian independent of inputs""" test_orbitals = 4 single_amplitudes = randn(*(test_orbitals, ) * 2) double_amplitudes = randn(*(test_orbitals, ) * 4) generator = uccsd_generator(single_amplitudes, double_amplitudes) conj_generator = hermitian_conjugated(generator) self.assertEqual(generator, -1. * conj_generator) def test_uccsd_singlet_anti_hermitian(self): """Test that the singlet version is anti-Hermitian""" 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) conj_generator = hermitian_conjugated(generator) self.assertEqual(generator, -1. * conj_generator) 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_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_sparse_uccsd_generator_numpy_inputs(self): """Test numpy ndarray inputs to uccsd_generator that are sparse""" test_orbitals = 30 sparse_single_amplitudes = numpy.zeros((test_orbitals, test_orbitals)) sparse_double_amplitudes = numpy.zeros( (test_orbitals, test_orbitals, test_orbitals, test_orbitals)) sparse_single_amplitudes[3, 5] = 0.12345 sparse_single_amplitudes[12, 4] = 0.44313 sparse_double_amplitudes[0, 12, 6, 2] = 0.3434 sparse_double_amplitudes[1, 4, 6, 13] = -0.23423 generator = uccsd_generator(sparse_single_amplitudes, sparse_double_amplitudes) test_generator = (0.12345 * FermionOperator("3^ 5") + (-0.12345) * FermionOperator("5^ 3") + 0.44313 * FermionOperator("12^ 4") + (-0.44313) * FermionOperator("4^ 12") + 0.3434 * FermionOperator("0^ 12 6^ 2") + (-0.3434) * FermionOperator("2^ 6 12^ 0") + (-0.23423) * FermionOperator("1^ 4 6^ 13") + 0.23423 * FermionOperator("13^ 6 4^ 1")) self.assertEqual(test_generator, generator) def test_sparse_uccsd_generator_list_inputs(self): """Test list inputs to uccsd_generator that are sparse""" sparse_single_amplitudes = [[[3, 5], 0.12345], [[12, 4], 0.44313]] sparse_double_amplitudes = [[[0, 12, 6, 2], 0.3434], [[1, 4, 6, 13], -0.23423]] generator = uccsd_generator(sparse_single_amplitudes, sparse_double_amplitudes) test_generator = (0.12345 * FermionOperator("3^ 5") + (-0.12345) * FermionOperator("5^ 3") + 0.44313 * FermionOperator("12^ 4") + (-0.44313) * FermionOperator("4^ 12") + 0.3434 * FermionOperator("0^ 12 6^ 2") + (-0.3434) * FermionOperator("2^ 6 12^ 0") + (-0.23423) * FermionOperator("1^ 4 6^ 13") + 0.23423 * FermionOperator("13^ 6 4^ 1")) self.assertEqual(test_generator, generator) def test_uccsd_singlet_get_packed_amplitudes(self): test_orbitals = 6 test_electrons = 2 sparse_single_amplitudes = numpy.zeros((test_orbitals, test_orbitals)) sparse_double_amplitudes = numpy.zeros( (test_orbitals, test_orbitals, test_orbitals, test_orbitals)) sparse_single_amplitudes[2, 0] = 0.12345 sparse_single_amplitudes[3, 1] = 0.12345 sparse_double_amplitudes[2, 0, 3, 1] = 0.9 sparse_double_amplitudes[2, 0, 4, 0] = 0.3434 sparse_double_amplitudes[5, 1, 3, 1] = 0.3434 packed_amplitudes = uccsd_singlet_get_packed_amplitudes( sparse_single_amplitudes, sparse_double_amplitudes, test_orbitals, test_electrons) self.assertEqual(len(packed_amplitudes), 5) self.assertTrue( numpy.allclose(packed_amplitudes, numpy.array([0.12345, 0., 0.9, 0., 0.3434]))) def test_ucc_h2(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) # Test UCCSD for accuracy against FCI using loaded t amplitudes. ucc_operator = uccsd_generator(self.molecule.ccsd_single_amps, self.molecule.ccsd_double_amps) hf_state = jw_hartree_fock_state(self.molecule.n_electrons, count_qubits(self.qubit_hamiltonian)) uccsd_sparse = jordan_wigner_sparse(ucc_operator) uccsd_state = scipy.sparse.linalg.expm_multiply(uccsd_sparse, hf_state) expected_uccsd_energy = expectation(self.hamiltonian_matrix, uccsd_state) self.assertAlmostEqual(expected_uccsd_energy, self.molecule.fci_energy, places=4) print("UCCSD ENERGY: {}".format(expected_uccsd_energy)) # Test CCSD for precise match against FCI using loaded t amplitudes. ccsd_operator = uccsd_generator(self.molecule.ccsd_single_amps, self.molecule.ccsd_double_amps, anti_hermitian=False) ccsd_sparse_r = jordan_wigner_sparse(ccsd_operator) ccsd_sparse_l = jordan_wigner_sparse( -hermitian_conjugated(ccsd_operator)) ccsd_state_r = scipy.sparse.linalg.expm_multiply( ccsd_sparse_r, hf_state) ccsd_state_l = scipy.sparse.linalg.expm_multiply( ccsd_sparse_l, hf_state) expected_ccsd_energy = ccsd_state_l.conjugate().dot( self.hamiltonian_matrix.dot(ccsd_state_r)) self.assertAlmostEqual(expected_ccsd_energy, self.molecule.fci_energy) def test_ucc_h2_singlet(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) # Test UCCSD for accuracy against FCI using loaded t amplitudes. ucc_operator = uccsd_generator(self.molecule.ccsd_single_amps, self.molecule.ccsd_double_amps) hf_state = jw_hartree_fock_state(self.molecule.n_electrons, count_qubits(self.qubit_hamiltonian)) uccsd_sparse = jordan_wigner_sparse(ucc_operator) uccsd_state = scipy.sparse.linalg.expm_multiply(uccsd_sparse, hf_state) expected_uccsd_energy = expectation(self.hamiltonian_matrix, uccsd_state) self.assertAlmostEqual(expected_uccsd_energy, self.molecule.fci_energy, places=4) print("UCCSD ENERGY: {}".format(expected_uccsd_energy)) # Test CCSD singlet for precise match against FCI using loaded t # amplitudes packed_amplitudes = uccsd_singlet_get_packed_amplitudes( self.molecule.ccsd_single_amps, self.molecule.ccsd_double_amps, self.molecule.n_qubits, self.molecule.n_electrons) ccsd_operator = uccsd_singlet_generator(packed_amplitudes, self.molecule.n_qubits, self.molecule.n_electrons, anti_hermitian=False) ccsd_sparse_r = jordan_wigner_sparse(ccsd_operator) ccsd_sparse_l = jordan_wigner_sparse( -hermitian_conjugated(ccsd_operator)) ccsd_state_r = scipy.sparse.linalg.expm_multiply( ccsd_sparse_r, hf_state) ccsd_state_l = scipy.sparse.linalg.expm_multiply( ccsd_sparse_l, hf_state) expected_ccsd_energy = ccsd_state_l.conjugate().dot( self.hamiltonian_matrix.dot(ccsd_state_r)) self.assertAlmostEqual(expected_ccsd_energy, self.molecule.fci_energy) def test_value_error_for_odd_n_qubits(self): # Pass odd n_qubits to singlet generators with self.assertRaises(ValueError): _ = uccsd_singlet_paramsize(3, 4) def test_value_error_bad_amplitudes(self): with self.assertRaises(ValueError): _ = uccsd_singlet_generator([1.], 3, 4)