Ejemplo n.º 1
0
    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)
Ejemplo n.º 2
0
    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 = []
Ejemplo n.º 3
0
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
Ejemplo n.º 4
0
    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
Ejemplo n.º 5
0
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 \
Ejemplo n.º 6
0
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)
Ejemplo n.º 7
0
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])