quantumlib / OpenFermion

The electronic structure package for quantum computers.
Apache License 2.0
1.52k stars 374 forks source link

Initial UCCSD amplitudes from MP2 #245

Open Konjkov opened 6 years ago

Konjkov commented 6 years ago

Hello OpenFermion developers

I need the method (can contribute code) for generation of initial amplitudes for UCCSD from MP2 amplitudes as formula is well known.

I do not quite understand what kind of class this should be, but if it would MolecularData the next code is valid for closed shell system

    @property
    def mp2_computed_energy(self):

        nocc = self.n_electrons // 2
        orbe = self.orbital_energies
        moints = self.two_body_integrals[:nocc, nocc:, :nocc, nocc:]
        E_occ, E_virt = orbe[:nocc], orbe[nocc:]

        denominator = 1/(
            E_occ.reshape(-1, 1, 1, 1) -
            E_virt.reshape(1, -1, 1, 1) +
            E_occ.reshape(1, 1, -1, 1) -
            E_virt.reshape(1, 1, 1, -1)
        )

        singlet = np.einsum(
            'iajb,iajb,iajb->',
            moints, moints, denominator
        )
        triplet = np.einsum(
            'iajb,iajb,iajb->',
            moints - moints.swapaxes(1, 3),
            moints, denominator
        )
        return singlet + triplet

    @property
    def uccsd_initial_amplitudes(self):

        nocc = self.n_electrons // 2
        orbe = self.orbital_energies
        moints = self.two_body_integrals[:nocc, nocc:, :nocc, nocc:]
        E_occ, E_virt = orbe[:nocc], orbe[nocc:]

        denominator = 1/(
            E_occ.reshape(-1, 1, 1, 1) -
            E_virt.reshape(1, -1, 1, 1) +
            E_occ.reshape(1, 1, -1, 1) -
            E_virt.reshape(1, 1, 1, -1)
        )
        return (moints.swapaxes(1, 3) - 2 * moints) * denominator

Also I've found that Powell minimization method is more stable than CG.

Best Vladimir.

jarrodmcc commented 6 years ago

Sorry for the delay in getting to this, I think it is a good idea to have such a function. I think there are two ways one could think about introducing this into the package. One (the simplest) would be to contribute these as functions to the unitary coupled cluster files in uccsd that take MolecularData structures as input. For this it would also be good to check if it's stored first, and use the stored value if so. The second way, would be to put properties like you have directly in MolecularData, where first it checks if the value is computed, and if not computes it. That one is a little trickier, as you need to make sure the saving and loading to files is all working out okay. I would suggest starting with the first way, and maybe transitioning to the second later if it makes sense. Do you need suggestions on how to go about making your first pull request?

Konjkov commented 6 years ago

Hello Jarrod I think that this code depends on this https://github.com/quantumlib/OpenFermion/pull/257

Also I do not quite understand how you are going to separate the closed shell and open shell cases. In the first case, the number of qubits should be half as much because of the symmetry between the alpha and beta orbitals, the same applies to amplitudes.

I think one can somehow implement also and ROHF case so each paired alpha and beta electron share same orbital but unpaired electron has its own one.

But because the transformation of the two-electron integrals from the AO to the MO basis is already done and stored in MolecularData, this function is not so computationally expensive to make it lazy.

Best Vladimir.

babbush commented 6 years ago

We merged #257 - did that clarify things?

Konjkov commented 6 years ago

I'm sorry for delay. Will have a look on holidays.