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 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_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_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 get_molecular_data(interaction_operator, geometry=None, basis=None, multiplicity=None, n_electrons=None, reduce_spin=True, data_directory=None): """Output a MolecularData object generated from an InteractionOperator Args: interaction_operator(InteractionOperator): two-body interaction operator defining the "molecular interaction" to be simulated. geometry(string or list of atoms): basis(string): String denoting the basis set used to discretize the system. multiplicity(int): Spin multiplicity desired in the system. n_electrons(int): Number of electrons in the system reduce_spin(bool): True if one wishes to perform spin reduction on integrals that are given in interaction operator. Assumes spatial (x) spin structure generically. Returns: molecule(MolecularData): Instance that captures the interaction_operator converted into the format that would come from an electronic structure package adorned with some meta-data that may be useful. """ n_spin_orbitals = interaction_operator.n_qubits # Introduce bare molecular operator to fill molecule = MolecularData(geometry=geometry, basis=basis, multiplicity=multiplicity, data_directory=data_directory) molecule.nuclear_repulsion = interaction_operator.constant # Remove spin from integrals and put into molecular operator if reduce_spin: reduction_indices = list(range(0, n_spin_orbitals, 2)) else: reduction_indices = list(range(n_spin_orbitals)) molecule.n_orbitals = len(reduction_indices) molecule.one_body_integrals = interaction_operator.one_body_tensor[ numpy.ix_(reduction_indices, reduction_indices)] molecule.two_body_integrals = interaction_operator.two_body_tensor[ numpy.ix_(reduction_indices, reduction_indices, reduction_indices, reduction_indices)] # Fill in other metadata molecule.overlap_integrals = numpy.eye(molecule.n_orbitals) molecule.n_qubits = n_spin_orbitals molecule.n_electrons = n_electrons molecule.multiplicity = multiplicity return molecule
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_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 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 __init__(self, geometry=None, basis=None, multiplicity=None, charge=0, description="", filename="", data_directory=None): MolecularData.__init__(self, geometry, basis, multiplicity, charge, description, filename, data_directory) self._pyscf_data = {}
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 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 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 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 test_rhf_min(): filename = os.path.join(DATA_DIRECTORY, "H2_sto-3g_singlet_0.7414.hdf5") molecule = MolecularData(filename=filename) overlap = molecule.overlap_integrals mo_obi = molecule.one_body_integrals mo_tbi = molecule.two_body_integrals rotation_mat = molecule.canonical_orbitals.T.dot(overlap) obi = general_basis_change(mo_obi, rotation_mat, (1, 0)) tbi = general_basis_change(mo_tbi, rotation_mat, (1, 1, 0, 0)) hff = HartreeFockFunctional(one_body_integrals=obi, two_body_integrals=tbi, overlap=overlap, n_electrons=molecule.n_electrons, model='rhf', nuclear_repulsion=molecule.nuclear_repulsion) result = rhf_minimization(hff) assert isinstance(result, OptimizeResult) result2 = rhf_minimization(hff, initial_guess=np.array([0]), sp_options={ 'maxiter': 100, 'disp': False }) assert isinstance(result2, OptimizeResult) assert np.isclose(result2.fun, result.fun)
def __init__(self, name, geometry, multiplicity, charge, n_orbitals, n_electrons, basis='sto-3g', frozen_els=None): self.name = name self.multiplicity = multiplicity self.charge = charge self.basis = basis self.geometry = geometry self.molecule_data = MolecularData(geometry=self.geometry, basis=basis, multiplicity=self.multiplicity, charge=self.charge) self.molecule_psi4 = run_psi4( self.molecule_data, run_fci=True) # old version of openfermion # Hamiltonian transforms self.molecule_ham = self.molecule_psi4.get_molecular_hamiltonian() self.hf_energy = self.molecule_psi4.hf_energy.item( ) # old version of openfermion self.fci_energy = self.molecule_psi4.fci_energy.item( ) # old version of openfermion # TODO: the code below corresponds to the most recent version in the opefermion documentation. # However it has problems with ray??? # calculate_molecule_psi4 = run_pyscf(self.molecule_data, run_scf=True, run_cisd=True, run_fci=True) # self.molecule_ham = calculate_molecule_psi4.get_molecular_hamiltonian() # self.hf_energy = calculate_molecule_psi4.hf_energy # self.fci_energy = float(calculate_molecule_psi4.fci_energy) # del calculate_molecule_psi4 self.energy_eigenvalues = None # use this only if calculating excited states if frozen_els is None: self.n_electrons = n_electrons self.n_orbitals = n_orbitals self.n_qubits = n_orbitals self.fermion_ham = get_fermion_operator(self.molecule_ham) else: self.n_electrons = n_electrons - len(frozen_els['occupied']) self.n_orbitals = n_orbitals - len(frozen_els['occupied']) - len( frozen_els['unoccupied']) self.n_qubits = self.n_orbitals self.fermion_ham = freeze_orbitals( get_fermion_operator(self.molecule_ham), occupied=frozen_els['occupied'], unoccupied=frozen_els['unoccupied'], prune=True) self.jw_qubit_ham = jordan_wigner(self.fermion_ham) # this is used only for calculating excited states. list of [term_index, term_state] self.H_lower_state_terms = None
def test_d2_to_g2(): # this should test for correctness filename = os.path.join(DATA_DIRECTORY, "H1-Li1_sto-3g_singlet_1.45.hdf5") molecule = MolecularData(filename=filename) molecule.load() opdm = molecule.fci_one_rdm tpdm = molecule.fci_two_rdm phdm = map_two_pdm_to_particle_hole_dm(tpdm, opdm) db = tpdm_to_phdm_mapping(molecule.n_qubits) topdm = Tensor(tensor=opdm, name='ck') ttpdm = Tensor(tensor=np.einsum('ijlk', tpdm), name='cckk') tphdm = Tensor(tensor=np.einsum('ijlk', phdm), name='ckck') mt = MultiTensor(tensors=[topdm, ttpdm, tphdm], dual_basis=db) A, _, b = mt.synthesize_dual_basis() vec_rdms = mt.vectorize_tensors() assert np.isclose(np.linalg.norm(A.dot(vec_rdms) - b), 0)
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_oqdm_to_opdm(self): for file in filter(lambda x: x.endswith(".hdf5"), os.listdir(DATA_DIRECTORY)): molecule = MolecularData( filename=os.path.join(DATA_DIRECTORY, file)) if molecule.fci_one_rdm is not None: true_oqdm = numpy.eye(molecule.n_qubits) - molecule.fci_one_rdm test_opdm = map_one_hole_dm_to_one_pdm(true_oqdm) assert numpy.allclose(test_opdm, molecule.fci_one_rdm)
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 test_gradient_lih(): filename = os.path.join(DATA_DIRECTORY, "H1-Li1_sto-3g_singlet_1.45.hdf5") molecule = MolecularData(filename=filename) overlap = molecule.overlap_integrals mo_obi = molecule.one_body_integrals mo_tbi = molecule.two_body_integrals rotation_mat = molecule.canonical_orbitals.T.dot(overlap) obi = general_basis_change(mo_obi, rotation_mat, (1, 0)) tbi = general_basis_change(mo_tbi, rotation_mat, (1, 1, 0, 0)) hff = HartreeFockFunctional(one_body_integrals=obi, two_body_integrals=tbi, overlap=overlap, n_electrons=molecule.n_electrons, model='rhf', nuclear_repulsion=molecule.nuclear_repulsion) params = np.random.randn(hff.nocc * hff.nvirt) u = sp.linalg.expm( rhf_params_to_matrix(params, hff.num_orbitals, occ=hff.occ, virt=hff.virt)) grad_dim = hff.nocc * hff.nvirt initial_opdm = np.diag([1] * hff.nocc + [0] * hff.nvirt) final_opdm = u.dot(initial_opdm).dot(u.conj().T) grad = hff.rhf_global_gradient(params, final_opdm) # get finite difference gradient finite_diff_grad = np.zeros(grad_dim) epsilon = 0.0001 for i in range(grad_dim): params_epsilon = params.copy() params_epsilon[i] += epsilon u = sp.linalg.expm( rhf_params_to_matrix(params_epsilon, hff.num_orbitals, occ=hff.occ, virt=hff.virt)) tfinal_opdm = u.dot(initial_opdm).dot(u.conj().T) energy_plus_epsilon = hff.energy_from_rhf_opdm(tfinal_opdm) params_epsilon[i] -= 2 * epsilon u = sp.linalg.expm( rhf_params_to_matrix(params_epsilon, hff.num_orbitals, occ=hff.occ, virt=hff.virt)) tfinal_opdm = u.dot(initial_opdm).dot(u.conj().T) energy_minus_epsilon = hff.energy_from_rhf_opdm(tfinal_opdm) finite_diff_grad[i] = (energy_plus_epsilon - energy_minus_epsilon) / (2 * epsilon) assert np.allclose(finite_diff_grad, grad, atol=epsilon)
def test_tpdm_to_opdm(self): # for all files in datadirectory check if this map holds for file in filter(lambda x: x.endswith(".hdf5"), os.listdir(DATA_DIRECTORY)): molecule = MolecularData( filename=os.path.join(DATA_DIRECTORY, file)) if (molecule.fci_one_rdm is not None and molecule.fci_two_rdm is not None): test_opdm = map_two_pdm_to_one_pdm(molecule.fci_two_rdm, molecule.n_electrons) assert numpy.allclose(test_opdm, molecule.fci_one_rdm)
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 test_generate_hamiltonian(): filename = os.path.join(DATA_DIRECTORY, "H1-Li1_sto-3g_singlet_1.45.hdf5") molecule = MolecularData(filename=filename) mo_obi = molecule.one_body_integrals mo_tbi = molecule.two_body_integrals mol_ham = generate_hamiltonian(mo_obi, mo_tbi, constant=0) assert isinstance(mol_ham, InteractionOperator) assert np.allclose(mol_ham.one_body_tensor[::2, ::2], mo_obi) assert np.allclose(mol_ham.one_body_tensor[1::2, 1::2], mo_obi) assert np.allclose(mol_ham.two_body_tensor[::2, ::2, ::2, ::2], 0.5 * mo_tbi) assert np.allclose(mol_ham.two_body_tensor[1::2, 1::2, 1::2, 1::2], 0.5 * mo_tbi)
def test_tqdm_conversions_lih_sto3g(self): filename = "H1-Li1_sto-3g_singlet_1.45.hdf5" molecule = MolecularData( filename=os.path.join(DATA_DIRECTORY, filename)) true_tqdm = self.tqdm_lih_sto3g test_tqdm = map_two_pdm_to_two_hole_dm(molecule.fci_two_rdm, molecule.fci_one_rdm) assert numpy.allclose(true_tqdm, test_tqdm) true_oqdm = numpy.eye(molecule.n_qubits) - molecule.fci_one_rdm test_oqdm = map_two_hole_dm_to_one_hole_dm( true_tqdm, molecule.n_qubits - molecule.n_electrons) assert numpy.allclose(true_oqdm, test_oqdm) test_tpdm = map_two_hole_dm_to_two_pdm(true_tqdm, molecule.fci_one_rdm) assert numpy.allclose(test_tpdm, molecule.fci_two_rdm)
def test_phdm_conversions_h2_sto3g(self): filename = "H2_sto-3g_singlet_1.4.hdf5" molecule = MolecularData( filename=os.path.join(DATA_DIRECTORY, filename)) true_phdm = self.phdm_h2_sto3g test_phdm = map_two_pdm_to_particle_hole_dm(molecule.fci_two_rdm, molecule.fci_one_rdm) assert numpy.allclose(test_phdm, true_phdm) test_opdm = map_particle_hole_dm_to_one_pdm(true_phdm, molecule.n_electrons, molecule.n_qubits) assert numpy.allclose(test_opdm, molecule.fci_one_rdm) test_tpdm = map_particle_hole_dm_to_two_pdm(true_phdm, molecule.fci_one_rdm) assert numpy.allclose(test_tpdm, molecule.fci_two_rdm)
def test_tqdm_conversions_h2_631g(self): # construct the 2-hole-RDM for LiH the slow way # TODO: speed up this calculation by directly contracting from the wf. filename = "H2_6-31g_singlet_0.75.hdf5" molecule = MolecularData( filename=os.path.join(DATA_DIRECTORY, filename)) true_tqdm = self.tqdm_h2_6_31g test_tqdm = map_two_pdm_to_two_hole_dm(molecule.fci_two_rdm, molecule.fci_one_rdm) assert numpy.allclose(true_tqdm, test_tqdm) true_oqdm = numpy.eye(molecule.n_qubits) - molecule.fci_one_rdm test_oqdm = map_two_hole_dm_to_one_hole_dm( true_tqdm, molecule.n_qubits - molecule.n_electrons) assert numpy.allclose(true_oqdm, test_oqdm) test_tpdm = map_two_hole_dm_to_two_pdm(true_tqdm, molecule.fci_one_rdm) assert numpy.allclose(test_tpdm, molecule.fci_two_rdm)
def test_rhf_func_generator(): filename = os.path.join(DATA_DIRECTORY, "H1-Li1_sto-3g_singlet_1.45.hdf5") molecule = MolecularData(filename=filename) overlap = molecule.overlap_integrals mo_obi = molecule.one_body_integrals mo_tbi = molecule.two_body_integrals rotation_mat = molecule.canonical_orbitals.T.dot(overlap) obi = general_basis_change(mo_obi, rotation_mat, (1, 0)) tbi = general_basis_change(mo_tbi, rotation_mat, (1, 1, 0, 0)) hff = HartreeFockFunctional(one_body_integrals=obi, two_body_integrals=tbi, overlap=overlap, n_electrons=molecule.n_electrons, model='rhf', nuclear_repulsion=molecule.nuclear_repulsion) unitary, energy, gradient = rhf_func_generator(hff) assert isinstance(unitary, Callable) assert isinstance(energy, Callable) assert isinstance(gradient, Callable) params = np.random.randn(hff.nocc * hff.nvirt) u = unitary(params) assert np.allclose(u.conj().T.dot(u), np.eye(hff.num_orbitals)) assert isinstance(energy(params), float) assert isinstance(gradient(params), np.ndarray) _, _, _, opdm_func = rhf_func_generator(hff, get_opdm_func=True) assert isinstance(opdm_func, Callable) assert isinstance(opdm_func(params), np.ndarray) assert np.isclose(opdm_func(params).shape[0], hff.num_orbitals) _, energy, _ = rhf_func_generator(hff, init_occ_vec=np.array([1, 1, 1, 1, 0, 0])) assert isinstance(energy(params), float)
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 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))