Skip to content

Inconsistency between expectation values via SparseHamiltonian and get_restricted_hamiltonian? #99

@cvjjm

Description

@cvjjm

Suppose I have an OpenFermion InteractionOperator and I want to measure its energy on a FQE wave function.

It appears there are two routs to do this:

  1. Convert the InteractionOperator to a FermionOperator and then to a FQE SparseHamiltonian (btw, it would be nice if there was a more direct way to do this)

  2. Get the tensors from the InteractionOperator and feed them into FQE's get_restricted_hamiltonian()

Naively I would have thought that this should yield the same result, but this does not seem to be the case, not even in the HartreeFock state as the following "minimal" example shows (just to be sure I am also constructing the InteractionOperator in two different ways):

import fqe
import numpy as np
import openfermion as of

from openfermion.chem.molecular_data import spinorb_from_spatial

def integrals_to_coefficients(one_body_integrals, two_body_integrals):
    return spinorb_from_spatial(one_body_integrals, two_body_integrals/2)

nact = 2
nalpha = 1
nbeta = 1

core_energy = 0.12345134
one_body_integrals = np.array([[-1.37560394, -0.26984563],
                               [-0.26984563,  1.09725617]])
two_body_integrals = np.array([[[[-0.56763992,  0.24989089],
                                 [ 0.24989089, -0.50890225]],
                                [[ 0.24989089, -0.50890225],
                                 [ 0.45668102, -0.21692285]]],
                               [[[ 0.24989089,  0.45668102],
                                 [-0.50890225, -0.21692285]],
                                [[-0.50890225, -0.21692285],
                                 [-0.21692285, -1.23529049]]]])

# make InteractionOperator manually
one_body_coefficients, two_body_coefficients = integrals_to_coefficients(one_body_integrals, two_body_integrals)
interaction_operator1 = of.InteractionOperator(core_energy, one_body_coefficients, two_body_coefficients)

# make InteractionOperator via MolecularData
molecule = of.MolecularData(
    geometry=[['?', [0, 0, 0]]],
    basis='cc-pvdz',
    multiplicity=nalpha-nbeta+1,
)
molecule.n_orbitals = nact
molecule.n_qubits = 2 * molecule.n_orbitals
molecule.nuclear_repulsion = core_energy
molecule.one_body_integrals = one_body_integrals
molecule.two_body_integrals = two_body_integrals
interaction_operator2 = molecule.get_molecular_hamiltonian()

wfn = fqe.Wavefunction([[nalpha+nbeta, nalpha-nbeta, nact]])
wfn.set_wfn(strategy="hartree-fock")

for interaction_operator in [interaction_operator1, interaction_operator2]:
    # btw: Is there a better way to transform an InteractionOperator into a FermionOperator?
    fermion_operator = of.FermionOperator()
    for key in interaction_operator:
        fermion_operator += of.FermionOperator(key, interaction_operator[key])
    fermion_operator = fqe.hamiltonians.sparse_hamiltonian.SparseHamiltonian(fermion_operator)
    print("SparseHamiltonian energy:           ", wfn.expectationValue(fermion_operator))

    fermion_operator = fqe.get_restricted_hamiltonian(
        ([interaction_operator.one_body_tensor,
          interaction_operator.two_body_tensor]),
        e_0=interaction_operator.constant)
    print("get_restricted_hamiltonian() energy:", wfn.expectationValue(fermion_operator))

The output I get is:

SparseHamiltonian energy:            (-3.19539646+0j)
get_restricted_hamiltonian() energy: (1.26736786+0j)
SparseHamiltonian energy:            (-3.19539646+0j)
get_restricted_hamiltonian() energy: (1.26736786+0j)

Am I doing something wrong?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions