def test_integration_jellium_hamiltonian_with_negation(self):
        hamiltonian = normal_ordered(
            jellium_model(Grid(2, 3, 1.), plane_wave=False))

        part_a = FermionOperator.zero()
        part_b = FermionOperator.zero()

        add_to_a_or_b = 0  # add to a if 0; add to b if 1
        for term, coeff in hamiltonian.terms.items():
            # Partition terms in the Hamiltonian into part_a or part_b
            if add_to_a_or_b:
                part_a += FermionOperator(term, coeff)
            else:
                part_b += FermionOperator(term, coeff)
            add_to_a_or_b ^= 1

        reference = normal_ordered(commutator(part_a, part_b))
        result = commutator_ordered_diagonal_coulomb_with_two_body_operator(
            part_a, part_b)

        self.assertTrue(result.isclose(reference))

        negative = commutator_ordered_diagonal_coulomb_with_two_body_operator(
            part_b, part_a)
        result += negative

        self.assertTrue(result.isclose(FermionOperator.zero()))
def benchmark_commutator_diagonal_coulomb_operators_2D_spinless_jellium(
        side_length):
    """Test speed of computing commutators using specialized functions.

    Args:
        side_length: The side length of the 2D jellium grid. There are
            side_length ** 2 qubits, and O(side_length ** 4) terms in the
            Hamiltonian.

    Returns:
        runtime_commutator: The time it takes to compute a commutator, after
            partitioning the terms and normal ordering, using the regular
            commutator function.
        runtime_diagonal_commutator: The time it takes to compute the same
            commutator using methods restricted to diagonal Coulomb operators.
    """
    hamiltonian = normal_ordered(
        jellium_model(Grid(2, side_length, 1.), plane_wave=False))

    part_a = FermionOperator.zero()
    part_b = FermionOperator.zero()
    add_to_a_or_b = 0  # add to a if 0; add to b if 1
    for term, coeff in hamiltonian.terms.items():
        # Partition terms in the Hamiltonian into part_a or part_b
        if add_to_a_or_b:
            part_a += FermionOperator(term, coeff)
        else:
            part_b += FermionOperator(term, coeff)
        add_to_a_or_b ^= 1

    start = time.time()
    _ = normal_ordered(commutator(part_a, part_b))
    end = time.time()
    runtime_commutator = end - start

    start = time.time()
    _ = commutator_ordered_diagonal_coulomb_with_two_body_operator(
        part_a, part_b)
    end = time.time()
    runtime_diagonal_commutator = end - start

    return runtime_commutator, runtime_diagonal_commutator
import numpy

import cirq
import openfermion

from openfermioncirq.variational.ansatzes import SplitOperatorTrotterAnsatz

# Construct a Hubbard model Hamiltonian
hubbard_model = openfermion.fermi_hubbard(2, 2, 1., 4.)
hubbard_hamiltonian = openfermion.get_diagonal_coulomb_hamiltonian(
    hubbard_model)

# Construct a jellium model Hamiltonian
grid = openfermion.Grid(2, 2, 1.0)
jellium = openfermion.jellium_model(grid, spinless=True, plane_wave=False)
jellium_hamiltonian = openfermion.get_diagonal_coulomb_hamiltonian(jellium)

# Construct a Hamiltonian of ones
ones_hamiltonian = openfermion.DiagonalCoulombHamiltonian(one_body=numpy.ones(
    (5, 5)),
                                                          two_body=numpy.ones(
                                                              (5, 5)))


def test_split_operator_trotter_ansatz_params():

    ansatz = SplitOperatorTrotterAnsatz(hubbard_hamiltonian)
    assert (set(ansatz.params()) == {
        cirq.Symbol(name)
        for name in {
# Set parameters of jellium model.
wigner_seitz_radius = 5.  # Radius per electron in Bohr radii.
n_dimensions = 2  # Number of spatial dimensions.
grid_length = 3  # Number of grid points in each dimension.
spinless = True  # Whether to include spin degree of freedom or not.
n_electrons = 2  # Number of electrons.

# Figure out length scale based on Wigner-Seitz radius and construct a basis grid.
length_scale = openfermion.wigner_seitz_length_scale(wigner_seitz_radius,
                                                     n_electrons, n_dimensions)
grid = openfermion.Grid(n_dimensions, grid_length, length_scale)

# Initialize the model and compute its ground energy in the correct particle number manifold
fermion_hamiltonian = openfermion.jellium_model(grid,
                                                spinless=spinless,
                                                plane_wave=False)
hamiltonian_sparse = openfermion.get_sparse_operator(fermion_hamiltonian)
ground_energy, _ = openfermion.jw_get_ground_state_at_particle_number(
    hamiltonian_sparse, n_electrons)
print('The ground energy of the jellium Hamiltonian at {} electrons is {}'.
      format(n_electrons, ground_energy))

# Convert to DiagonalCoulombHamiltonian type.
hamiltonian = openfermion.get_diagonal_coulomb_hamiltonian(fermion_hamiltonian)

# Define the objective function
objective = openfermioncirq.HamiltonianObjective(hamiltonian)

# Create a swap network Trotter ansatz.
iterations = 1  # This is the number of Trotter steps to use in the ansatz.