def test_fermionic_hamiltonian_from_integrals(self): constant = self.molecule.nuclear_repulsion doci_constant = constant hc, hr1, hr2 = get_doci_from_integrals( self.molecule.one_body_integrals, self.molecule.two_body_integrals) doci = DOCIHamiltonian(doci_constant, hc, hr1, hr2) doci_qubit_op = doci.qubit_operator doci_mat = get_sparse_operator(doci_qubit_op).toarray() #doci_eigvals, doci_eigvecs = numpy.linalg.eigh(doci_mat) doci_eigvals, _ = numpy.linalg.eigh(doci_mat) tensors = doci.n_body_tensors one_body_tensors, two_body_tensors = tensors[(1, 0)], tensors[(1, 1, 0, 0)] fermion_op1 = get_fermion_operator( InteractionOperator(constant, one_body_tensors, 0. * two_body_tensors)) fermion_op2 = get_fermion_operator( InteractionOperator(0, 0 * one_body_tensors, 0.5 * two_body_tensors)) import openfermion as of fermion_op1_jw = of.transforms.jordan_wigner(fermion_op1) fermion_op2_jw = of.transforms.jordan_wigner(fermion_op2) fermion_op_jw = fermion_op1_jw + fermion_op2_jw #fermion_eigvals, fermion_eigvecs = numpy.linalg.eigh( # get_sparse_operator(fermion_op_jw).toarray()) fermion_eigvals, _ = numpy.linalg.eigh( get_sparse_operator(fermion_op_jw).toarray()) for eigval in doci_eigvals: assert any(abs(fermion_eigvals - eigval) < 1e-6), "The DOCI spectrum should \ have been contained in the spectrum of the fermionic operators" fermion_diagonal = get_sparse_operator( fermion_op_jw).toarray().diagonal() qubit_diagonal = doci_mat.diagonal() assert numpy.isclose( fermion_diagonal[0], qubit_diagonal[0] ) and numpy.isclose( fermion_diagonal[-1], qubit_diagonal[-1] ), "The first and last elements of hte qubit and fermionic diagonal of \ the Hamiltonian maxtrix should be the same as the vaccum should be \ mapped to the computational all zero state and the completely filled \ state should be mapped to the all one state" print(fermion_diagonal) print(qubit_diagonal)
def __init__( self, molecule=MolecularData, iter_max=30, run_parallel=False, verbose=True, ): oei, tei = molecule.get_integrals() elec_hamil = RestrictedHamiltonian((oei, np.einsum("ijlk", -0.5 * tei))) oei, tei = molecule.get_integrals() soei, stei = spinorb_from_spatial(oei, tei) astei = np.einsum('ijkl', stei) - np.einsum('ijlk', stei) molecular_hamiltonian = InteractionOperator(0, soei, 0.25 * astei) # moleham = molecule.get_molecular_hamiltonian() reduced_ham = make_reduced_hamiltonian(molecular_hamiltonian, molecule.n_electrons) self.molecule = molecule self.reduced_ham = reduced_ham self.elec_hamil = elec_hamil self.iter_max = iter_max self.sdim = elec_hamil.dim() # change to use multiplicity to derive this for open shell self.nalpha = molecule.n_electrons // 2 self.nbeta = molecule.n_electrons // 2 self.sz = self.nalpha - self.nbeta if PARALLELIZABLE and run_parallel: self.parallel = True else: self.parallel = False self.verbose = verbose # store results self.acse_energy = []
def _get_diagonal_component_interaction_operator(interaction_operator): """Get the component of an interaction operator that is diagonal in the computational basis under Jordan-Wigner transformation (i.e., the terms that can be expressed as products of number operators). Args: interaction_operator (openfermion.ops.InteractionOperator): the operator Returns: tuple: two openfermion.ops.InteractionOperator objects. The first is the diagonal component, and the second is the remainder. """ one_body_tensor = np.zeros( interaction_operator.one_body_tensor.shape, dtype=complex ) two_body_tensor = np.zeros( interaction_operator.two_body_tensor.shape, dtype=complex ) diagonal_op = InteractionOperator( interaction_operator.constant, one_body_tensor, two_body_tensor ) one_body_tensor = np.copy(interaction_operator.one_body_tensor).astype(complex) two_body_tensor = np.copy(interaction_operator.two_body_tensor).astype(complex) remainder_op = InteractionOperator(0.0, one_body_tensor, two_body_tensor) n_spin_orbitals = interaction_operator.two_body_tensor.shape[0] for p in range(n_spin_orbitals): for q in range(n_spin_orbitals): diagonal_op.two_body_tensor[ p, q, p, q ] = interaction_operator.two_body_tensor[p, q, p, q] diagonal_op.two_body_tensor[ p, q, q, p ] = interaction_operator.two_body_tensor[p, q, q, p] remainder_op.two_body_tensor[p, q, p, q] = 0.0 remainder_op.two_body_tensor[p, q, q, p] = 0.0 for p in range(n_spin_orbitals): diagonal_op.one_body_tensor[p, p] = interaction_operator.one_body_tensor[p, p] remainder_op.one_body_tensor[p, p] = 0.0 return diagonal_op, remainder_op
def __init__(self, oei: np.ndarray, tei: np.ndarray, operator_pool, n_alpha: int, n_beta: int, iter_max=30, verbose=True, stopping_epsilon=1.0E-3, delta_e_eps=1.0E-6): """ ADAPT-VQE object. Args: oei: one electron integrals in the spatial basis tei: two-electron integrals in the spatial basis operator_pool: Object with .op_pool that is a list of antihermitian FermionOperators n_alpha: Number of alpha-electrons n_beta: Number of beta-electrons iter_max: Maximum ADAPT-VQE steps to take verbose: Print the iteration information stopping_epsilon: define the <[G, H]> value that triggers stopping """ elec_hamil = RestrictedHamiltonian((oei, np.einsum("ijlk", -0.5 * tei))) soei, stei = spinorb_from_spatial(oei, tei) astei = np.einsum('ijkl', stei) - np.einsum('ijlk', stei) molecular_hamiltonian = InteractionOperator(0, soei, 0.25 * astei) reduced_ham = make_reduced_hamiltonian(molecular_hamiltonian, n_alpha + n_beta) self.reduced_ham = reduced_ham self.k2_ham = of.get_fermion_operator(reduced_ham) self.k2_fop = build_hamiltonian(self.k2_ham, elec_hamil.dim(), conserve_number=True) self.elec_hamil = elec_hamil self.iter_max = iter_max self.sdim = elec_hamil.dim() # change to use multiplicity to derive this for open shell self.nalpha = n_alpha self.nbeta = n_beta self.sz = self.nalpha - self.nbeta self.nele = self.nalpha + self.nbeta self.verbose = verbose self.operator_pool = operator_pool self.stopping_eps = stopping_epsilon self.delta_e_eps = delta_e_eps
def test_fermionic_hamiltonian_from_integrals(g, n_qubits): rg = RichardsonGaudin(g, n_qubits) #hc, hr1, hr2 = rg.hc, rg.hr1, rg.hr2 doci = rg constant = doci.constant reference_constant = 0 doci_qubit_op = doci.qubit_operator doci_mat = get_sparse_operator(doci_qubit_op).toarray() doci_eigvals = np.linalg.eigh(doci_mat)[0] tensors = doci.n_body_tensors one_body_tensors, two_body_tensors = tensors[(1, 0)], tensors[(1, 1, 0, 0)] fermion_op = get_fermion_operator( InteractionOperator(constant, one_body_tensors, 0.5 * two_body_tensors)) fermion_op = normal_ordered(fermion_op) fermion_mat = get_sparse_operator(fermion_op).toarray() fermion_eigvals = np.linalg.eigh(fermion_mat)[0] one_body_tensors2, two_body_tensors2 = rg.get_antisymmetrized_tensors() fermion_op2 = get_fermion_operator( InteractionOperator(reference_constant, one_body_tensors2, 0.5 * two_body_tensors2)) fermion_op2 = normal_ordered(fermion_op2) fermion_mat2 = get_sparse_operator(fermion_op2).toarray() fermion_eigvals2 = np.linalg.eigh(fermion_mat2)[0] for eigval in doci_eigvals: assert any(abs(fermion_eigvals - eigval) < 1e-6), "The DOCI spectrum should have \ been contained in the spectrum of the fermionic operator constructed via the \ DOCIHamiltonian class" for eigval in doci_eigvals: assert any(abs(fermion_eigvals2 - eigval) < 1e-6), "The DOCI spectrum should have \
def convert_dict_to_interaction_op(dictionary: dict) -> InteractionOperator: """Get an InteractionOperator from a dictionary. Args: dictionary (dict): the dictionary representation Returns: op (openfermion.ops.InteractionOperator): the operator """ # The tolist method is used to convert the constant from a zero-dimensional array to a float/complex constant = convert_dict_to_array(dictionary["constant"]).tolist() one_body_tensor = convert_dict_to_array(dictionary["one_body_tensor"]) two_body_tensor = convert_dict_to_array(dictionary["two_body_tensor"]) return InteractionOperator(constant, one_body_tensor, two_body_tensor)
def test_get_one_qubit_hydrogen_hamiltonian(): # Define interaction hamiltonian h2_hamiltonian_int = InteractionOperator(constant=constant, one_body_tensor=one_body_tensor, two_body_tensor=two_body_tensor) save_interaction_operator(h2_hamiltonian_int, 'interaction-operator.json') get_one_qubit_hydrogen_hamiltonian('interaction-operator.json') h2_1qubit = load_qubit_operator('qubit-operator.json') h2_1qubit_sparse = get_sparse_operator(h2_1qubit, n_qubits=1) h2_1qubit_dense = h2_1qubit_sparse.toarray() #print(h2_1qubit_dense) e_1q = eigvalsh(h2_1qubit_dense) gs_4q = get_ground_state(get_sparse_operator(h2_hamiltonian_int)) os.remove('interaction-operator.json') os.remove('qubit-operator.json') assert isclose(e_1q[0], gs_4q[0])