Ejemplo n.º 1
0
def get_interaction_rdm(qubit_operator, n_qubits=None):
    """Build an InteractionRDM from measured qubit operators.

    Returns: An InteractionRDM object.
    """
    # Avoid circular import.
    from openfermion.transforms import jordan_wigner
    if n_qubits is None:
        n_qubits = count_qubits(qubit_operator)
    one_rdm = numpy.zeros((n_qubits, ) * 2, dtype=complex)
    two_rdm = numpy.zeros((n_qubits, ) * 4, dtype=complex)

    # One-RDM.
    for i, j in itertools.product(range(n_qubits), repeat=2):
        transformed_operator = jordan_wigner(FermionOperator(((i, 1), (j, 0))))
        for term, coefficient in iteritems(transformed_operator.terms):
            if term in qubit_operator.terms:
                one_rdm[i, j] += coefficient * qubit_operator.terms[term]

    # Two-RDM.
    for i, j, k, l in itertools.product(range(n_qubits), repeat=4):
        transformed_operator = jordan_wigner(
            FermionOperator(((i, 1), (j, 1), (k, 0), (l, 0))))
        for term, coefficient in iteritems(transformed_operator.terms):
            if term in qubit_operator.terms:
                two_rdm[i, j, k, l] += coefficient * qubit_operator.terms[term]

    return InteractionRDM(one_rdm, two_rdm)
Ejemplo n.º 2
0
def energy_from_opdm(opdm, constant, one_body_tensor, two_body_tensor):
    """
    Evaluate the energy of an opdm assuming the 2-RDM is opdm ^ opdm

    :param opdm: single spin-component of the full spin-orbital opdm.
    :param constant: constant shift to the Hamiltonian. Commonly this is the
                     nuclear repulsion energy.
    :param one_body_tensor: spatial one-body integrals
    :param two_body_tensor: spatial two-body integrals
    :return:
    """
    spin_opdm = np.kron(opdm, np.eye(2))
    spin_tpdm = 2 * wedge(spin_opdm, spin_opdm, (1, 1), (1, 1))
    molecular_hamiltonian = generate_hamiltonian(constant=constant,
                                                 one_body_integrals=one_body_tensor,
                                                 two_body_integrals=two_body_tensor)
    rdms = InteractionRDM(spin_opdm, spin_tpdm)
    return rdms.expectation(molecular_hamiltonian).real
Ejemplo n.º 3
0
    def get_molecular_rdm_spin(self, use_fci=False):
        """Method to return 1-RDM and 2-RDMs from CISD or FCI, adapted for
           spin-orbitals.

        Args:
            use_fci: Boolean indicating whether to use RDM from FCI
                calculation.

        Returns:
            rdm: An instance of the MolecularRDM class.

        Raises:
            MisissingCalculationError: If the CI calculation has not been
                performed.
        """
        # Make sure requested RDM has been computed and load.
        if use_fci:
            if self.fci_energy is None:
                raise MissingCalculationError(
                    'Missing FCI RDM in {}'.format(self.filename) +
                    'Run FCI calculation before loading FCI RDMs.')
            else:
                one_rdm = self.fci_one_rdm
                two_rdm = self.fci_two_rdm
        else:
            if self.cisd_energy is None:
                raise MissingCalculationError(
                    'Missing CISD RDM in {}'.format(self.filename) +
                    'Run CISD calculation before loading CISD RDMs.')
            else:
                one_rdm = self.cisd_one_rdm
                two_rdm = self.cisd_two_rdm

        one_rdm = numpy.kron(one_rdm/2,numpy.eye(2))

        #two_rdm
        n_qubits = one_rdm.shape[0]                

        new_two_rdm = numpy.zeros((n_qubits, n_qubits,n_qubits, n_qubits))
        for p in range(n_qubits // 2):
            for q in range(n_qubits // 2):
                for r in range(n_qubits // 2):
                    for s in range(n_qubits // 2):
                        new_two_rdm[2 * p, 2 * q + 1, 2 * r + 1, 2 * s] = (two_rdm[p, q, r, s] / 2.)
                        new_two_rdm[2 * p + 1, 2 * q, 2 * r, 2 * s + 1] = (two_rdm[p, q, r, s] / 2.)
                        new_two_rdm[2 * p, 2 * q + 1, 2 * r, 2 * s + 1] = -(two_rdm[p, q, r, s] / 2.)
                        new_two_rdm[2 * p + 1, 2 * q, 2 * r + 1, 2 * s] = -(two_rdm[p, q, r, s] / 2.)
        # Truncate.
        one_rdm[numpy.absolute(one_rdm) < EQ_TOLERANCE] = 0.
        new_two_rdm[numpy.absolute(new_two_rdm) < EQ_TOLERANCE] = 0.

        # Cast to InteractionRDM class.
        rdm = InteractionRDM(one_rdm, new_two_rdm)
        return rdm
Ejemplo n.º 4
0
    def rdms_from_opdm_aa(self, opdm_aa):
        """
        Generate InteractionRDM for the problem from opdm_aa

        :param opdm_aa:
        :return:
        """
        opdm = np.zeros((self.num_qubits, self.num_qubits), dtype=complex)
        opdm[::2, ::2] = opdm_aa
        opdm[1::2, 1::2] = opdm_aa
        tpdm = wedge(opdm, opdm, (1, 1), (1, 1))
        rdms = InteractionRDM(opdm, 2 * tpdm)
        return rdms
def test_qiskitpauli_to_qubitop_type_enforced():
    """Enforce the appropriate type"""
    create_one = FermionOperator("1^")
    empty_one_body = np.zeros((2, 2))
    empty_two_body = np.zeros((2, 2, 2, 2))
    interact_one = InteractionOperator(1, empty_one_body, empty_two_body)
    interact_rdm = InteractionRDM(empty_one_body, empty_two_body)

    with pytest.raises(TypeError):
        qiskitpauli_to_qubitop(create_one)
    with pytest.raises(TypeError):
        qiskitpauli_to_qubitop(interact_one)
    with pytest.raises(TypeError):
        qiskitpauli_to_qubitop(interact_rdm)
Ejemplo n.º 6
0
    def rdms_from_opdm_aa(self, opdm_aa) -> InteractionRDM:
        """Generate the RDM from just the alpha-alpha block.

        Due to symmetry, the beta-beta block is the same, and the other
        blocks are zero.

        Args:
            opdm_aa: The alpha-alpha block of the RDM
        """
        opdm = np.zeros((self.num_qubits, self.num_qubits), dtype=complex)
        opdm[::2, ::2] = opdm_aa
        opdm[1::2, 1::2] = opdm_aa
        tpdm = wedge(opdm, opdm, (1, 1), (1, 1))
        rdms = InteractionRDM(opdm, 2 * tpdm)
        return rdms
def test_translation_type_enforcement():
    """
    Make sure type check works
    """
    create_one = FermionOperator("1^")
    empty_one_body = np.zeros((2, 2))
    empty_two_body = np.zeros((2, 2, 2, 2))
    interact_one = InteractionOperator(1, empty_one_body, empty_two_body)
    interact_rdm = InteractionRDM(empty_one_body, empty_two_body)

    with pytest.raises(TypeError):
        qubitop_to_qiskitpauli(create_one)
    with pytest.raises(TypeError):
        qubitop_to_qiskitpauli(interact_one)
    with pytest.raises(TypeError):
        qubitop_to_qiskitpauli(interact_rdm)
    def rdms_from_rhf_opdm(self, opdm_aa: np.ndarray) -> InteractionRDM:
        """
        Generate spin-orbital InteractionRDM object from the alpha-spin
        opdm.

        Args:
            opdm_aa: single spin sector of the 1-particle denstiy matrix

        Returns:  InteractionRDM object for full spin-orbital 1-RDM and 2-RDM
        """

        opdm = np.zeros((2 * self.num_orbitals, 2 * self.num_orbitals),
                        dtype=np.complex128)
        opdm[::2, ::2] = opdm_aa
        opdm[1::2, 1::2] = opdm_aa
        tpdm = wedge(opdm, opdm, (1, 1), (1, 1))
        rdms = InteractionRDM(opdm, 2 * tpdm)
        return rdms
Ejemplo n.º 9
0
def get_expectation_values_from_rdms(
    interactionrdm: InteractionRDM,
    qubitoperator: QubitOperator,
    sort_terms: bool = False,
) -> ExpectationValues:
    """Computes expectation values of Pauli strings in a QubitOperator given a fermionic InteractionRDM from
       OpenFermion.

    Args:
        interactionrdm: interaction RDM to use for the expectation values
            computation, as an OF InteractionRDM object
        qubitoperator: qubit operator to compute the expectation values for
            in the form of an OpenFermion QubitOperator object
        sort_terms: whether or not the input qubit operator needs to be sorted before calculating expectations
    Returns:
        expectation values of Pauli strings in the qubit operator as an ExpectationValues object
    """
    if sort_terms:
        terms_iterator = sorted(qubitoperator.terms.items(),
                                key=lambda x: abs(x[1]),
                                reverse=True)
    else:
        terms_iterator = qubitoperator.terms.items()
    reordered_qubitoperator = QubitOperator()
    for term, coefficient in terms_iterator:
        reordered_qubitoperator += QubitOperator(term, coefficient)

    expectations_packed = interactionrdm.get_qubit_expectations(
        reordered_qubitoperator)

    if () in expectations_packed.terms:
        del expectations_packed.terms[(
        )]  # Expectation of the constant term is excluded from expectation values

    expectations = np.array(list(expectations_packed.terms.values()))
    if np.any(np.abs(np.imag(expectations)) > 1e-3):
        raise RuntimeWarning(
            f"Expectation values extracted from rdms inside get_expectation_values_from_rdms are complex!"
        )
    expectations = np.real(expectations)
    np.clip(expectations, -1, 1, out=expectations)

    return ExpectationValues(expectations)
Ejemplo n.º 10
0
def test_pyquil_to_qubitop_type_enforced():
    """Enforce the appropriate type"""
    create_one = FermionOperator("1^")
    empty_one_body = np.zeros((2, 2))
    empty_two_body = np.zeros((2, 2, 2, 2))
    interact_one = InteractionOperator(1, empty_one_body, empty_two_body)
    interact_rdm = InteractionRDM(empty_one_body, empty_two_body)

    with pytest.raises(TypeError):
        pyquilpauli_to_qubitop(create_one)
    with pytest.raises(TypeError):
        pyquilpauli_to_qubitop(interact_one)
    with pytest.raises(TypeError):
        pyquilpauli_to_qubitop(interact_rdm)

    # don't accept anything other than pyquil PauliSum or PauliTerm
    with pytest.raises(TypeError):
        pyquilpauli_to_qubitop(create_one)
    with pytest.raises(TypeError):
        pyquilpauli_to_qubitop(interact_one)
    with pytest.raises(TypeError):
        pyquilpauli_to_qubitop(interact_rdm)
Ejemplo n.º 11
0
    def get_molecular_rdm(self, use_fci=False):
        """Method to return 1-RDM and 2-RDMs from CISD or FCI.

        Args:
            use_fci: Boolean indicating whether to use RDM from FCI
                calculation.

        Returns:
            rdm: An instance of the MolecularRDM class.

        Raises:
            MisissingCalculationError: If the CI calculation has not been
                performed.
        """
        # Make sure requested RDM has been computed and load.
        if use_fci:
            if self.fci_energy is None:
                raise MissingCalculationError(
                    'Missing FCI RDM in {}'.format(self.filename) +
                    'Run FCI calculation before loading FCI RDMs.')
            else:
                one_rdm = self.fci_one_rdm
                two_rdm = self.fci_two_rdm
        else:
            if self.cisd_energy is None:
                raise MissingCalculationError(
                    'Missing CISD RDM in {}'.format(self.filename) +
                    'Run CISD calculation before loading CISD RDMs.')
            else:
                one_rdm = self.cisd_one_rdm
                two_rdm = self.cisd_two_rdm

        # Truncate.
        one_rdm[numpy.absolute(one_rdm) < EQ_TOLERANCE] = 0.
        two_rdm[numpy.absolute(two_rdm) < EQ_TOLERANCE] = 0.

        # Cast to InteractionRDM class.
        rdm = InteractionRDM(one_rdm, two_rdm)
        return rdm
Ejemplo n.º 12
0
def test_translation_type_enforcement():
    """
    Make sure type check works
    """
    create_one = FermionOperator("1^")
    empty_one_body = np.zeros((2, 2))
    empty_two_body = np.zeros((2, 2, 2, 2))
    interact_one = InteractionOperator(1, empty_one_body, empty_two_body)
    interact_rdm = InteractionRDM(empty_one_body, empty_two_body)

    with pytest.raises(TypeError):
        qubitop_to_pyquilpauli(create_one)
    with pytest.raises(TypeError):
        qubitop_to_pyquilpauli(interact_one)
    with pytest.raises(TypeError):
        qubitop_to_pyquilpauli(interact_rdm)

    # don't accept anything other than pyquil PauliSum or PauliTerm
    with pytest.raises(TypeError):
        qubitop_to_pyquilpauli(create_one)
    with pytest.raises(TypeError):
        qubitop_to_pyquilpauli(interact_one)
    with pytest.raises(TypeError):
        qubitop_to_pyquilpauli(interact_rdm)