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) np_ham = of.get_number_preserving_sparse_operator( of.get_fermion_operator(reduced_ham), molecule.n_qubits, num_electrons=molecule.n_electrons, spin_preserving=True) w, _ = np.linalg.eigh(np_ham.toarray()) assert np.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) np_ham = of.get_number_preserving_sparse_operator( of.get_fermion_operator(reduced_ham), molecule.n_qubits, num_electrons=molecule.n_electrons, spin_preserving=True) w, _ = np.linalg.eigh(np_ham.toarray()) assert np.isclose(molecule.fci_energy, w[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 plot_data(bond_lengths, data): basis = 'sto-3g' multiplicity = 1 bond_length_interval = 0.1 n_points = 25 # Generate molecule at different bond lengths. hf_energies = [] fci_energies = [] for bond_length in bond_lengths: description = str(round(bond_length, 2)) # print(description) geometry = [('H', (0., 0., 0.)), ('H', (0., 0., bond_length))] molecule = MolecularData(geometry, basis, multiplicity, description=description) # Load data. molecule.load() hf_energies += [molecule.hf_energy] fci_energies += [molecule.fci_energy] plt.figure(0) plt.plot(bond_lengths, fci_energies, 'x-') plt.plot(bond_lengths, [e for e, _ in data], 'o-') plt.ylabel('Energy in Hartree') plt.xlabel('Bond length in angstrom') plt.show()
def get_openfermion_molecule(geometry, basis, charge, multiplicity, calc_type='fci'): """ Get openfermion molecule objects :param geometry: list of tuples where first element of the tuple is the atom string, and next three coordinates are XYZ geom :param basis: (string) of basis set :param multiplicity: eigenvalue of S^{2} (2S + 1) :param charge: (int) charge on molecule :param calc_type: (string) valid calculation types are: ['scf', 'mp2', 'cisd', 'ccsd', 'fci']. default is 'fci' if 'fci' is selected the fci_one_rdm and fci_two_rdm fields are populated and can be used later. Conversion to particle and holes can occur with methods in the representability.purification.fermionic_marginal :return: """ valid_calc_types = ['scf', 'mp2', 'cisd', 'ccsd', 'fci'] if calc_type not in valid_calc_types: raise TypeError("Calculation type is not valid") molecule = MolecularData(geometry, basis, multiplicity, charge) # get the calculation type run_scf = 1 run_mp2 = 0 run_cisd = 0 run_ccsd = 0 run_fci = 1 # default to fci run molecule = run_psi4(molecule, run_scf=run_scf, run_mp2=run_mp2, run_cisd=run_cisd, run_ccsd=run_ccsd, run_fci=run_fci) return molecule
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 get_qubit_hamiltonian(mol, geometry, basis, charge=0, multiplicity=1, qubit_transf='bk'): ''' Generating qubit hamiltonina of the given molecules with specified geometry, basis sets, charge and multiplicity Give its qubit form using specified transformation ''' g = get_molecular_data(mol, geometry) mol = MolecularData(g, basis, multiplicity, charge) mol = run_pyscf(mol) ham = mol.get_molecular_hamiltonian() hamf = get_fermion_operator(ham) if qubit_transf == 'bk': hamq = bravyi_kitaev(hamf) elif qubit_transf == 'jw': hamq = jordan_wigner(hamf) else: raise (ValueError(qubit_transf, 'Unknown transformation specified')) return hamq
def do_make_molecule(self, *args, **kwargs): """ Parameters ---------- args kwargs Returns ------- """ # integrals need to be passed in base class assert ("one_body_integrals" in kwargs) assert ("two_body_integrals" in kwargs) assert ("nuclear_repulsion" in kwargs) assert ("n_orbitals" in kwargs) molecule = MolecularData(**self.parameters.molecular_data_param) molecule.one_body_integrals = kwargs["one_body_integrals"] molecule.two_body_integrals = kwargs["two_body_integrals"] molecule.nuclear_repulsion = kwargs["nuclear_repulsion"] molecule.n_orbitals = kwargs["n_orbitals"] molecule.save() return molecule
def system_h4(): print('Running System Setup H4') basis = 'sto-3g' multiplicity = 1 charge = 0 r = 0.75 geometry = [('H', [0.0, 0.0, 0.0]), ('H', [0, 0, r]), ('H', [0, 0, 2 * r]), ('H', [0, 0, 3 * r])] molecule = MolecularData(geometry, basis, multiplicity, charge) # Run Psi4. molecule = run_psi4(molecule, run_scf=True, run_mp2=False, run_cisd=False, run_ccsd=False, run_fci=True, delete_input=False) op_mat = of.get_sparse_operator( molecule.get_molecular_hamiltonian()).toarray() w, v = np.linalg.eigh(op_mat) n_density = v[:, [0]] @ v[:, [0]].conj().T rdm_generator = AntiSymmOrbitalDensity(n_density, molecule.n_qubits) transform = jordan_wigner return n_density, rdm_generator, transform, molecule
def make_molecule(self, *args, **kwargs) -> MolecularData: """Creates a molecule in openfermion format by running psi4 and extracting the data Will check for previous outputfiles before running Will not recompute if a file was found Parameters ---------- parameters : An instance of ParametersQC, which also holds an instance of ParametersPsi4 via parameters.psi4 The molecule will be saved in parameters.filename, if this file exists before the call the molecule will be imported from the file Returns ------- type the molecule in openfermion.MolecularData format """ molecule = MolecularData(**self.parameters.molecular_data_param) # try to load do_compute = True try: import os if os.path.exists(self.parameters.filename): molecule.load() do_compute = False except OSError: do_compute = True if do_compute: molecule = self.do_make_molecule(*args, **kwargs) molecule.save() return molecule
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_erpa_eom_ham_h2(): 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) rha_fermion = of.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 * of.wedge(opdm, opdm, (1, 1), (1, 1)) rdms = of.InteractionRDM(opdm, tpdm) dim = reduced_ham.one_body_tensor.shape[0] // 2 full_basis = {} # erpa basis. A, B basis in RPA language cnt = 0 for p, q in product(range(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 = of.FermionOperator( ((2 * q + sigma, 1), (2 * p + sigma, 0))) rs_op = of.FermionOperator( ((2 * r + tau, 1), (2 * s + tau, 0))) erpa_op = of.normal_ordered( of.commutator(qp_op, of.commutator(rha_fermion, rs_op))) true = rdms.expectation(of.get_interaction_operator(erpa_op)) assert np.isclose(true, test)
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 create_molecule(): geometry = make_geometry() basis = 'sto-3g' charge = 0 multiplicity = 1 moleculefilename = '/app/moleculefile.hdf5' molecule = MolecularData(geometry, basis, multiplicity, charge, description, filename=moleculefilename) # openfermion's run_psi4 molecule = run_psi4(molecule, run_scf=1, run_mp2=1, run_cisd=0, run_ccsd=0, run_fci=0, verbose=1, tolerate_error=1) molecule.save()
def exp_hamiltoniantrot_H2(time, atomic_distance, trotter_order): """ Here we are using some packages related to quantum chemistry to obtain hamiltonian of H2 molecule. The we are translating this hamiltonian into sequence of pyquil gates. And finally, we are trotterazing the exponent of the hamiltonian (exp(-iHt)) of our system and returning the obtained pyquil program :param time: is t in the exp(iHt). Note the + sign. :param atomic_distance: the distance between to H atoms in H2 molecule :return: program of the Trotter-Suzuki decomposition of hamiltonian exp(iHt) for H2 molecule """ geometry = [['H', [0, 0, 0]], ['H', [0, 0, atomic_distance]]] # H--H distance = 0.74angstrom basis = 'sto-3g' multiplicity = 1 # (2S+1) charge = 0 h2_molecule = MolecularData(geometry, basis, multiplicity, charge) h2_molecule = run_pyscf(h2_molecule) h2_qubit_hamiltonian = jordan_wigner(get_fermion_operator(h2_molecule.get_molecular_hamiltonian())) pyquil_h2_qubit_hamiltonian = qubitop_to_pyquilpauli(h2_qubit_hamiltonian) return trotterization(pyquil_h2_qubit_hamiltonian, float(time), trotter_order)
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 h_n_linear_molecule(bond_distance: float, n_hydrogens: int, basis: str = 'sto-3g'): # coverage: ignore if n_hydrogens < 1 or n_hydrogens % 2 != 0: raise ValueError('Must specify a positive, even number of hydrogens.') molecule = MolecularData( geometry=_h_n_linear_geometry(bond_distance, n_hydrogens), charge=0, basis=basis, multiplicity=1, description=f"linear_r-{bond_distance}", ) if NO_OFPSI4: raise NOOFPsi4Error("openfermion-psi4 is not installed") molecule = run_psi4(molecule, run_fci=False, run_mp2=False, run_cisd=False, run_ccsd=False, delete_input=False, delete_output=False) return molecule
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 decompose_hamiltonian(mol_name, hf_data, mapping="jordan_wigner", docc_mo_indices=None, active_mo_indices=None): r"""Decomposes the electronic Hamiltonian into a linear combination of Pauli operators using OpenFermion tools. **Example usage:** >>> decompose_hamiltonian('h2', './pyscf/sto-3g/', mapping='bravyi_kitaev') (-0.04207897696293986+0j) [] + (0.04475014401986122+0j) [X0 Z1 X2] + (0.04475014401986122+0j) [X0 Z1 X2 Z3] +(0.04475014401986122+0j) [Y0 Z1 Y2] + (0.04475014401986122+0j) [Y0 Z1 Y2 Z3] +(0.17771287459806262+0j) [Z0] + (0.17771287459806265+0j) [Z0 Z1] +(0.1676831945625423+0j) [Z0 Z1 Z2] + (0.1676831945625423+0j) [Z0 Z1 Z2 Z3] +(0.12293305054268105+0j) [Z0 Z2] + (0.12293305054268105+0j) [Z0 Z2 Z3] +(0.1705973832722409+0j) [Z1] + (-0.2427428049645989+0j) [Z1 Z2 Z3] +(0.1762764080276107+0j) [Z1 Z3] + (-0.2427428049645989+0j) [Z2] Args: mol_name (str): name of the molecule hf_data (str): path to the directory containing the file with the Hartree-Fock electronic structure mapping (str): optional argument to specify the fermion-to-qubit mapping Input values can be ``'jordan_wigner'`` or ``'bravyi_kitaev'`` docc_mo_indices (list): indices of doubly-occupied molecular orbitals, i.e., the orbitals that are not correlated in the many-body wave function active_mo_indices (list): indices of active molecular orbitals, i.e., the orbitals used to build the correlated many-body wave function Returns: transformed_operator: instance of the QubitOperator class representing the electronic Hamiltonian """ # loading HF data from a hdf5 file molecule = MolecularData( filename=os.path.join(hf_data.strip(), mol_name.strip())) # getting the terms entering the second-quantized Hamiltonian terms_molecular_hamiltonian = molecule.get_molecular_hamiltonian( occupied_indices=docc_mo_indices, active_indices=active_mo_indices) # generating the fermionic Hamiltonian fermionic_hamiltonian = get_fermion_operator(terms_molecular_hamiltonian) mapping = mapping.strip().lower() if mapping not in ("jordan_wigner", "bravyi_kitaev"): raise TypeError( "The '{}' transformation is not available. \n " "Please set 'mapping' to 'jordan_wigner' or 'bravyi_kitaev'.". format(mapping)) # fermionic-to-qubit transformation of the Hamiltonian if mapping == "bravyi_kitaev": return bravyi_kitaev(fermionic_hamiltonian) return jordan_wigner(fermionic_hamiltonian)
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 np.isclose(reduced_ham.constant, molecule.nuclear_repulsion) assert np.allclose(reduced_ham.one_body_tensor, 0)
def decompose(hf_file, mapping="jordan_wigner", core=None, active=None): r"""Decomposes the molecular Hamiltonian into a linear combination of Pauli operators using OpenFermion tools. This function uses OpenFermion functions to build the second-quantized electronic Hamiltonian of the molecule and map it to the Pauli basis using the Jordan-Wigner or Bravyi-Kitaev transformation. Args: hf_file (str): absolute path to the hdf5-formatted file with the Hartree-Fock electronic structure mapping (str): Specifies the transformation to map the fermionic Hamiltonian to the Pauli basis. Input values can be ``'jordan_wigner'`` or ``'bravyi_kitaev'``. core (list): indices of core orbitals, i.e., the orbitals that are not correlated in the many-body wave function active (list): indices of active orbitals, i.e., the orbitals used to build the correlated many-body wave function Returns: QubitOperator: an instance of OpenFermion's ``QubitOperator`` **Example** >>> decompose('./pyscf/sto-3g/h2', mapping='bravyi_kitaev') (-0.04207897696293986+0j) [] + (0.04475014401986122+0j) [X0 Z1 X2] + (0.04475014401986122+0j) [X0 Z1 X2 Z3] +(0.04475014401986122+0j) [Y0 Z1 Y2] + (0.04475014401986122+0j) [Y0 Z1 Y2 Z3] +(0.17771287459806262+0j) [Z0] + (0.17771287459806265+0j) [Z0 Z1] +(0.1676831945625423+0j) [Z0 Z1 Z2] + (0.1676831945625423+0j) [Z0 Z1 Z2 Z3] +(0.12293305054268105+0j) [Z0 Z2] + (0.12293305054268105+0j) [Z0 Z2 Z3] +(0.1705973832722409+0j) [Z1] + (-0.2427428049645989+0j) [Z1 Z2 Z3] +(0.1762764080276107+0j) [Z1 Z3] + (-0.2427428049645989+0j) [Z2] """ # loading HF data from the hdf5 file molecule = MolecularData(filename=hf_file.strip()) # getting the terms entering the second-quantized Hamiltonian terms_molecular_hamiltonian = molecule.get_molecular_hamiltonian( occupied_indices=core, active_indices=active ) # generating the fermionic Hamiltonian fermionic_hamiltonian = get_fermion_operator(terms_molecular_hamiltonian) mapping = mapping.strip().lower() if mapping not in ("jordan_wigner", "bravyi_kitaev"): raise TypeError( "The '{}' transformation is not available. \n " "Please set 'mapping' to 'jordan_wigner' or 'bravyi_kitaev'.".format(mapping) ) # fermionic-to-qubit transformation of the Hamiltonian if mapping == "bravyi_kitaev": return bravyi_kitaev(fermionic_hamiltonian) return jordan_wigner(fermionic_hamiltonian)
def generate_figure_1(): singlet_glob = glob.glob('molecule_data/*sto-3g_singlet*.hdf5') singlet_glob = sorted(singlet_glob) triplet_glob = glob.glob('molecule_data/*sto-3g_triplet*.hdf5') triplet_glob = sorted(triplet_glob) singlet_fci = [ float(MolecularData(filename=fn).fci_energy) for fn in singlet_glob ] triplet_fci = [ MolecularData(filename=fn).fci_energy for fn in triplet_glob ] xx = [float(MolecularData(filename=fn).description) for fn in singlet_glob] #print(singlet_fci) #print(triplet_fci) #print(xx) geometry = [('H', (0., 0., 0.)), ('H', (0., 0., 1.))] basis = 'sto-3g' multiplicity = 3 description = '1.0' filename = 'test_test_test_H2' molecule = MolecularData(geometry, basis, multiplicity, description=description, filename=filename) molecule = run_psi4(molecule, run_mp2=False, run_cisd=False, run_ccsd=True, run_fci=True) #molecule = MolecularData(filename=triplet_glob[0]) print('filename: {}'.format(molecule.filename)) print('n_atoms: {}'.format(molecule.n_atoms)) print('n_electrons: {}'.format(molecule.n_electrons)) print('n_orbitals: {}'.format(molecule.n_orbitals)) #print('Canonical Orbitals: {}'.format(molecule.canonical_orbitals)) print('n_qubits: {}'.format(molecule.n_qubits)) print(molecule.ccsd_energy) print(molecule.description) print(molecule.two_body_integrals) print(molecule.multiplicity)
def test_table_one_particle(core, active, t_op_exp): r"""Test the correctness of the FermionOperator built by the `'one_particle'` function of the `obs` module""" hf = MolecularData(filename=os.path.join(ref_dir, "h2o_psi4")) t_op = qchem.one_particle(hf.one_body_integrals, core=core, active=active) assert t_op.terms == t_op_exp
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 run_simulation(bond_lengths): # Load saved file for H3. basis = 'sto-3g' spin = 2 # Set Hamiltonian parameters. active_space_start = 1 active_space_stop = 3 # Set calculation parameters. run_scf = 1 run_mp2 = 1 run_cisd = 0 run_ccsd = 0 run_fci = 1 delete_input = True delete_output = True # Begin Running Simulation, Convert distance_counter to angstroms geometry = [('H', (0., 0., bond_lengths[1][-1] * 0.529177249)), ('H', (0., 0., bond_lengths[2][-1] * 0.529177249)), ('H', (0., 0., bond_lengths[3][-1] * 0.529177249))] # Generate and populate instance of MolecularData. molecule = MolecularData(geometry, basis, spin, description="h3") molecule = run_pyscf(molecule, run_scf=run_scf, run_mp2=run_mp2, run_cisd=run_cisd, run_ccsd=run_ccsd, run_fci=run_fci) # Use a Jordan-Wigner encoding, and compress to remove 0 imaginary components molecular_hamiltonian = molecule.get_molecular_hamiltonian( occupied_indices=range(active_space_start), active_indices=range(active_space_start, active_space_stop)) fermion_hamiltonian = get_fermion_operator(molecular_hamiltonian) qubit_hamiltonian = jordan_wigner(fermion_hamiltonian) qubit_hamiltonian.compress() compiler_engine = uccsd_trotter_engine() initial_energy = energy_objective(opt_amplitudes) # Run VQE Optimization to find new CCSD parameters opt_result = minimize(energy_objective, opt_amplitudes, method="CG", options={'disp': True}) opt_energy, opt_amplitudes = opt_result.fun, opt_result.x return ({ "Name": molecule.name, "UCCSD Energy": opt_energy, "FCI Energy": molecule.fci_energy })
def test_one_body_square_decomposition(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) two_body_coefficients = molecule_interaction.two_body_tensor # Decompose. eigenvalues, one_body_squares, one_body_correction, error = ( low_rank_two_body_decomposition(two_body_coefficients)) 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_unspin_adapt_1(): heh_file = os.path.join(DATA_DIRECTORY, 'H1-He1_sto-3g_singlet_1+_0.74.hdf5') molecule = MolecularData(filename=heh_file) tpdm_from_of = np.einsum('ijkl->ijlk', molecule.fci_two_rdm) rho, rdm_generator, transform, mol2 = system() assert np.allclose(np.conj(rho).T, rho) dim = molecule.n_qubits rdm_generator_antisym = AntiSymmOrbitalDensity(rho, molecule.n_qubits) tpdm_aa, tpdm_bb, tpdm_ab, [bas_aa, bas_ab ] = rdm_generator_antisym.construct_tpdm() assert np.allclose(opdm, molecule.fci_one_rdm) assert np.allclose(tpdm, tpdm_from_of) tpdm_test = unspin_adapt(tpdm_aa, tpdm_bb, tpdm_ab) # print(np.linalg.norm(tpdm[::2, ::2, ::2, ::2] - tpdm_test[::2, ::2, ::2, ::2])) np.testing.assert_allclose(tpdm[::2, ::2, ::2, ::2], tpdm_test[::2, ::2, ::2, ::2]) # print(np.linalg.norm(tpdm[1::2, 1::2, 1::2, 1::2] - tpdm_test[1::2, 1::2, 1::2, 1::2])) np.testing.assert_allclose(tpdm[1::2, 1::2, 1::2, 1::2], tpdm_test[1::2, 1::2, 1::2, 1::2]) # print(np.linalg.norm(tpdm[::2, 1::2, ::2, 1::2] - tpdm_test[::2, 1::2, ::2, 1::2])) np.testing.assert_allclose(tpdm[::2, 1::2, ::2, 1::2], tpdm_test[::2, 1::2, ::2, 1::2]) # print(np.linalg.norm(tpdm[1::2, ::2, 1::2, ::2] - tpdm_test[1::2, ::2, 1::2, ::2])) np.testing.assert_allclose(tpdm[1::2, ::2, 1::2, ::2], tpdm_test[1::2, ::2, 1::2, ::2]) for p, q, r, s in product(range(tpdm.shape[0]), repeat=4): if not np.isclose(tpdm[p, q, r, s], tpdm_test[p, q, r, s]): print((p, q, r, s), tpdm[p, q, r, s], tpdm_test[p, q, r, s]) heh_file = os.path.join(DATA_DIRECTORY, 'H1-He1_sto-3g_singlet_1+_0.74.hdf5') molecule = MolecularData(filename=heh_file) tpdm_from_of = np.einsum('ijkl->ijlk', molecule.fci_two_rdm) for p, q, r, s in product(range(tpdm.shape[0]), repeat=4): if not np.isclose(tpdm_from_of[p, q, r, s], tpdm[p, q, r, s]): print((p, q, r, s), tpdm_from_of[p, q, r, s], tpdm[p, q, r, s]) t_tpdm_aa, t_tpdm_bb, t_tpdm_ab = get_sz_spin_adapted(tpdm) assert np.allclose(t_tpdm_ab, tpdm_ab)
def test_table_two_particle(name, core, active, table_exp, v_core_exp, tol): r"""Test the table of two-particle matrix elements and the contribution of core orbitals as implemented in the `two_particle` function of the `obs` module""" hf_data = MolecularData(filename=os.path.join(ref_dir, name)) table, v_core = qchem.two_particle(hf_data.two_body_integrals, core=core, active=active) assert np.allclose(table, table_exp, **tol) assert np.allclose(v_core, v_core_exp, **tol)
def test_table_two_particle(name, core, active, v_op_exp): r"""Test the FermionOperator built by the function `two_particle` of the `obs` module""" hf_data = MolecularData(filename=os.path.join(ref_dir, name)) v_op = qchem.two_particle(hf_data.two_body_integrals, core=core, active=active) assert v_op.terms == v_op_exp
def get_BK_ham(distance, basis="sto-3g", multiplicity=1, charge=1): geometry = [["He", [0, 0, 0]], ["H", [0, 0, distance]]] description = str(distance) molecule = MolecularData(geometry, basis, multiplicity, charge, description) molecule = run_pyscf(molecule, run_fci=1) bk_hamiltonian = get_sparse_operator( bravyi_kitaev( get_fermion_operator(molecule.get_molecular_hamiltonian()))) return bk_hamiltonian
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)