Пример #1
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
Пример #2
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 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
Пример #4
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
Пример #5
0
    def global_gradient_opdm(self, params: np.ndarray, alpha_opdm: np.ndarray):
        opdm = np.zeros((self.num_qubits, self.num_qubits),
                        dtype=np.complex128)
        opdm[::2, ::2] = alpha_opdm
        opdm[1::2, 1::2] = alpha_opdm
        tpdm = 2 * wedge(opdm, opdm, (1, 1), (1, 1))

        # now go through and generate all the necessary Z, Y, Y_kl matrices
        kappa_matrix = rhf_params_to_matrix(params,
                                            len(self.occ) + len(self.virt),
                                            self.occ, self.virt)
        kappa_matrix_full = np.kron(kappa_matrix, np.eye(2))
        w_full, v_full = np.linalg.eigh(
            -1j * kappa_matrix_full)  # so that kappa = i U lambda U^
        eigs_scaled_full = get_matrix_of_eigs(w_full)

        grad = np.zeros(self.nocc * self.nvirt, dtype=np.complex128)
        kdelta = np.eye(self.num_qubits)

        # NOW GENERATE ALL TERMS ASSOCIATED WITH THE GRADIENT!!!!!!
        for p in range(self.nocc * self.nvirt):
            grad_params = np.zeros_like(params)
            grad_params[p] = 1
            Y = rhf_params_to_matrix(grad_params,
                                     len(self.occ) + len(self.virt), self.occ,
                                     self.virt)
            Y_full = np.kron(Y, np.eye(2))

            # Now rotate Y int othe basis that diagonalizes Z
            Y_kl_full = v_full.conj().T @ Y_full @ v_full
            # now rotate Y_{kl} * (exp(i(l_{k} - l_{l})) - 1) / (i(l_{k} - l_{l}))
            # into the original basis
            pre_matrix_full = v_full @ (eigs_scaled_full *
                                        Y_kl_full) @ v_full.conj().T

            grad_expectation = -1.0 * np.einsum(
                'ab,pq,aq,pb',
                self.hamiltonian.one_body_tensor,
                pre_matrix_full,
                kdelta,
                opdm,
                optimize='optimal').real
            grad_expectation += 1.0 * np.einsum(
                'ab,pq,bp,aq',
                self.hamiltonian.one_body_tensor,
                pre_matrix_full,
                kdelta,
                opdm,
                optimize='optimal').real
            grad_expectation += 1.0 * np.einsum(
                'ijkl,pq,iq,jpkl',
                self.hamiltonian.two_body_tensor,
                pre_matrix_full,
                kdelta,
                tpdm,
                optimize='optimal').real
            grad_expectation += -1.0 * np.einsum(
                'ijkl,pq,jq,ipkl',
                self.hamiltonian.two_body_tensor,
                pre_matrix_full,
                kdelta,
                tpdm,
                optimize='optimal').real
            grad_expectation += -1.0 * np.einsum(
                'ijkl,pq,kp,ijlq',
                self.hamiltonian.two_body_tensor,
                pre_matrix_full,
                kdelta,
                tpdm,
                optimize='optimal').real
            grad_expectation += 1.0 * np.einsum(
                'ijkl,pq,lp,ijkq',
                self.hamiltonian.two_body_tensor,
                pre_matrix_full,
                kdelta,
                tpdm,
                optimize='optimal').real
            grad[p] = grad_expectation

        return grad
    def rhf_global_gradient(self, params: np.ndarray, alpha_opdm: np.ndarray):
        """
        Compute rhf global gradient

        Args:
            params: rhf-parameters for rotation matrix.
            alpha_opdm: 1-RDM corresponding to results of basis rotation
                        parameterized by `params'.

        Returns: gradient vector the same size as the input `params'
        """
        opdm = np.zeros((2 * self.num_orbitals, 2 * self.num_orbitals),
                        dtype=np.complex128)
        opdm[::2, ::2] = alpha_opdm
        opdm[1::2, 1::2] = alpha_opdm
        tpdm = 2 * wedge(opdm, opdm, (1, 1), (1, 1))

        # now go through and generate all the necessary Z, Y, Y_kl matrices
        kappa_matrix = rhf_params_to_matrix(params,
                                            len(self.occ) + len(self.virt),
                                            self.occ, self.virt)
        kappa_matrix_full = np.kron(kappa_matrix, np.eye(2))
        w_full, v_full = np.linalg.eigh(
            -1j * kappa_matrix_full)  # so that kappa = i U lambda U^
        eigs_scaled_full = get_matrix_of_eigs(w_full)

        grad = np.zeros(self.nocc * self.nvirt, dtype=np.complex128)
        # kdelta = np.eye(2 * self.num_orbitals)

        # NOW GENERATE ALL TERMS ASSOCIATED WITH THE GRADIENT!!!!!!
        for p in range(self.nocc * self.nvirt):
            grad_params = np.zeros_like(params)
            grad_params[p] = 1
            Y = rhf_params_to_matrix(grad_params,
                                     len(self.occ) + len(self.virt), self.occ,
                                     self.virt)
            Y_full = np.kron(Y, np.eye(2))

            # Now rotate Y int othe basis that diagonalizes Z
            Y_kl_full = v_full.conj().T.dot(Y_full).dot(v_full)
            # now rotate Y_{kl} * (exp(i(l_{k} - l_{l})) - 1) / (i(l_{k} - l_{l}))
            # into the original basis
            pre_matrix_full = v_full.dot(eigs_scaled_full * Y_kl_full).dot(
                v_full.conj().T)

            grad_expectation = -1.0 * np.einsum(
                'ab,pa,pb',
                self.hamiltonian.one_body_tensor,
                pre_matrix_full,
                opdm,
                optimize='optimal').real

            grad_expectation += 1.0 * np.einsum(
                'ab,bq,aq',
                self.hamiltonian.one_body_tensor,
                pre_matrix_full,
                opdm,
                optimize='optimal').real

            grad_expectation += 1.0 * np.einsum(
                'ijkl,pi,jpkl',
                self.hamiltonian.two_body_tensor,
                pre_matrix_full,
                tpdm,
                optimize='optimal').real

            grad_expectation += -1.0 * np.einsum(
                'ijkl,pj,ipkl',
                self.hamiltonian.two_body_tensor,
                pre_matrix_full,
                tpdm,
                optimize='optimal').real

            grad_expectation += -1.0 * np.einsum(
                'ijkl,kq,ijlq',
                self.hamiltonian.two_body_tensor,
                pre_matrix_full,
                tpdm,
                optimize='optimal').real

            grad_expectation += 1.0 * np.einsum(
                'ijkl,lq,ijkq',
                self.hamiltonian.two_body_tensor,
                pre_matrix_full,
                tpdm,
                optimize='optimal').real
            grad[p] = grad_expectation

        return grad