Пример #1
0
def hf_rdm(n_alpha: int, n_beta: int, n_orbitals: int) -> InteractionRDM:
    """Construct the RDM corresponding to a Hartree-Fock state.

    Args:
        n_alpha (int): number of spin-up electrons
        n_beta (int): number of spin-down electrons
        n_orbitals (int): number of spatial orbitals (not spin orbitals)
    
    Returns:
        openfermion.ops.InteractionRDM: the reduced density matrix
    """
    # Determine occupancy of each spin orbital
    occ = np.zeros(2 * n_orbitals)
    occ[:(2 * n_alpha):2] = 1
    occ[1:(2 * n_beta + 1):2] = 1

    one_body_tensor = np.diag(occ)

    two_body_tensor = np.zeros([2 * n_orbitals for i in range(4)])
    for i in range(2 * n_orbitals):
        for j in range(2 * n_orbitals):
            if i != j and occ[i] and occ[j]:
                two_body_tensor[i, j, j, i] = 1
                two_body_tensor[i, j, i, j] = -1

    return InteractionRDM(one_body_tensor, two_body_tensor)
Пример #2
0
def get_rdms_from_psi4(wfn, ndocc=None, nact=None):

    """Get 1- and 2-RDMs from a Psi4 calculation.

    Args:
        wfn (psi4.core.Wavefunction): Psi4 wavefunction object
        ndocc (int): number of doubly occupied molecular orbitals to
            exclude from the saved RDM.
        nact (int): number of active molecular orbitals to include in the
            saved RDM.
    Returns:
        rdm (openfermion.ops.InteractionRDM): an openfermion object storing
            1- and 2-RDMs.
    """

    if nact is None and ndocc is None:
        ndocc = 0
        nact = wfn.Ca().to_array(dense=True).shape[1]
        print(
            f"Active space selection options were reset to: ndocc = {ndocc} and  nact = {nact}"
        )
    elif nact is not None and ndocc is None:
        assert nact <= wfn.Ca().to_array(dense=True).shape[1]
        ndocc = 0
        print(
            f"Active space selection options were reset to: ndocc = {ndocc} and  nact = {nact}"
        )
    elif ndocc is not None and nact is None:
        assert ndocc <= wfn.Ca().to_array(dense=True).shape[1]
        nact = wfn.Ca().to_array(dense=True).shape[1] - ndocc
        print(
            f"Active space selection options were reset to: ndocc = {ndocc} and  nact = {nact}"
        )

    one_rdm_a = np.array(wfn.get_opdm(0, 0, "A", True)).reshape(wfn.nmo(), wfn.nmo())
    one_rdm_b = np.array(wfn.get_opdm(0, 0, "B", True)).reshape(wfn.nmo(), wfn.nmo())

    # Get 2-RDM from CI calculation.

    assert nact == wfn.nmo() - wfn.nfrzc() - wfn.frzvpi().sum()
    assert ndocc == wfn.nfrzc()

    two_rdm_aa = np.array(wfn.get_tpdm("AA", False)).reshape(nact, nact, nact, nact)
    two_rdm_ab = np.array(wfn.get_tpdm("AB", False)).reshape(nact, nact, nact, nact)
    two_rdm_bb = np.array(wfn.get_tpdm("BB", False)).reshape(nact, nact, nact, nact)

    # adjusting 1-RDM
    # Indices of active molecular orbitals
    active_indices = range(ndocc, ndocc + nact)
    one_rdm_a = one_rdm_a[np.ix_(active_indices, active_indices)]
    one_rdm_b = one_rdm_b[np.ix_(active_indices, active_indices)]

    one_rdm, two_rdm = unpack_spatial_rdm(
        one_rdm_a, one_rdm_b, two_rdm_aa, two_rdm_ab, two_rdm_bb
    )

    rdms = InteractionRDM(one_rdm, two_rdm)

    return rdms
Пример #3
0
def convert_dict_to_interaction_rdm(dictionary):
    """Get an InteractionRDM from a dictionary.
    Args:
        dictionary (dict): the dictionary representation
    Returns:
        op (openfermion.ops.InteractionRDM): the operator
    """

    one_body_tensor = convert_dict_to_array(dictionary["one_body_tensor"])
    two_body_tensor = convert_dict_to_array(dictionary["two_body_tensor"])

    return InteractionRDM(one_body_tensor, two_body_tensor)
Пример #4
0
def get_ground_state_rdm_from_qubit_op(
    qubit_operator: QubitOperator, n_particles: int
) -> InteractionRDM:
    """Diagonalize operator and compute the ground state 1- and 2-RDM

    Args:
        qubit_operator (openfermion.QubitOperator): The openfermion operator to diagonalize
        n_particles (int): number of particles in the target ground state

    Returns:
        rdm (openfermion.InteractionRDM): interaction RDM of the ground state with the particle
            number n_particles
    """

    sparse_operator = get_sparse_operator(qubit_operator)
    e, ground_state_wf = jw_get_ground_state_at_particle_number(
        sparse_operator, n_particles
    )  # float/np.array pair
    n_qubits = count_qubits(qubit_operator)

    one_body_tensor = []
    for i in range(n_qubits):
        for j in range(n_qubits):
            idag_j = get_sparse_operator(
                FermionOperator(f"{i}^ {j}"), n_qubits=n_qubits
            )
            idag_j = idag_j.toarray()
            one_body_tensor.append(
                np.conjugate(ground_state_wf) @ idag_j @ ground_state_wf
            )

    one_body_tensor = np.array(one_body_tensor)
    one_body_tensor = one_body_tensor.reshape(n_qubits, n_qubits)

    two_body_tensor = np.zeros((n_qubits,) * 4, dtype=complex)
    for p in range(n_qubits):
        for q in range(0, p + 1):
            for r in range(n_qubits):
                for s in range(0, r + 1):
                    pdag_qdag_r_s = get_sparse_operator(
                        FermionOperator(f"{p}^ {q}^ {r} {s}"), n_qubits=n_qubits
                    )
                    pdag_qdag_r_s = pdag_qdag_r_s.toarray()
                    rdm_element = (
                        np.conjugate(ground_state_wf) @ pdag_qdag_r_s @ ground_state_wf
                    )
                    two_body_tensor[p, q, r, s] = rdm_element
                    two_body_tensor[q, p, r, s] = -rdm_element
                    two_body_tensor[q, p, s, r] = rdm_element
                    two_body_tensor[p, q, s, r] = -rdm_element

    return InteractionRDM(one_body_tensor, two_body_tensor)
Пример #5
0
 def setUp(self):
     n_modes = 2
     np.random.seed(0)
     one_body_tensor = np.random.rand(*(n_modes, ) * 2)
     two_body_tensor = np.random.rand(*(n_modes, ) * 4)
     self.interaction_rdm = InteractionRDM(one_body_tensor, two_body_tensor)
Пример #6
0
        [
            [0.0, -0.10410015, 0.0, 0.0],
            [0.10410015, 0.0, -0.0, 0.0],
            [0.0, 0.0, 0.0, 0.01095689],
            [-0.0, 0.0, -0.01095689, 0.0],
        ],
        [
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
            [0.0, 0.0, 0.0, 0.0],
        ],
    ],
])

rdms = InteractionRDM(rdm1, rdm2)


@pytest.mark.parametrize(
    "term1,term2,expected_result",
    [
        (((0, "Y"), ), ((0, "X"), ), False),
        (((0, "Y"), ), ((1, "X"), ), True),
        (((0, "Y"), (1, "X")), (), True),
    ],
)
def test_is_comeasureable(term1, term2, expected_result):
    assert is_comeasureable(term1, term2) == expected_result


@pytest.mark.parametrize(