#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

import numpy
import pytest

import cirq
import openfermion

from openfermioncirq import (
        HamiltonianObjective,
        LowRankTrotterAnsatz,
        SplitOperatorTrotterAnsatz,
        SwapNetworkTrotterAnsatz,
        SwapNetworkTrotterHubbardAnsatz,
        VariationalStudy,
        prepare_gaussian_state,
        simulate_trotter)
from openfermioncirq.trotter import (
        LINEAR_SWAP_NETWORK, LOW_RANK, LowRankTrotterAlgorithm, SPLIT_OPERATOR)


# 4-qubit random DiagonalCoulombHamiltonian
diag_coul_hamiltonian = openfermion.random_diagonal_coulomb_hamiltonian(
        4, real=True, seed=47141)

# 4-qubit H2 2-2 with bond length 0.7414
bond_length = 0.7414
geometry = [('H', (0., 0., 0.)), ('H', (0., 0., bond_length))]
h2_hamiltonian = openfermion.load_molecular_hamiltonian(
        geometry, 'sto-3g', 1, format(bond_length), 2, 2)

# 4-qubit LiH 2-2 with bond length 1.45
bond_length = 1.45
geometry = [('Li', (0., 0., 0.)), ('H', (0., 0., bond_length))]
lih_hamiltonian = openfermion.load_molecular_hamiltonian(
        geometry, 'sto-3g', 1, format(bond_length), 2, 2)


@pytest.mark.parametrize(
        'ansatz, trotter_algorithm, order, hamiltonian, atol', [
    (SwapNetworkTrotterAnsatz(diag_coul_hamiltonian, iterations=1),
        LINEAR_SWAP_NETWORK, 1, diag_coul_hamiltonian, 5e-5),
    (SplitOperatorTrotterAnsatz(diag_coul_hamiltonian, iterations=1),
        SPLIT_OPERATOR, 1, diag_coul_hamiltonian, 5e-5),
    (LowRankTrotterAnsatz(h2_hamiltonian, iterations=1),
        LOW_RANK, 0, h2_hamiltonian, 5e-5),
    (LowRankTrotterAnsatz(lih_hamiltonian, iterations=1, final_rank=3),
        LowRankTrotterAlgorithm(final_rank=3), 0, lih_hamiltonian, 5e-5),
    (SwapNetworkTrotterHubbardAnsatz(2, 2, 1.0, 4.0, iterations=1),
        LINEAR_SWAP_NETWORK, 1,
        openfermion.get_diagonal_coulomb_hamiltonian(
            openfermion.reorder(
                openfermion.fermi_hubbard(2, 2, 1.0, 4.0),
                openfermion.up_then_down)
        ),
        5e-5)
])
def test_trotter_ansatzes_default_initial_params_iterations_1(
        ansatz, trotter_algorithm, order, hamiltonian, atol):
    """Check that a Trotter ansatz with one iteration and default parameters
    is consistent with time evolution with one Trotter step."""

    objective = HamiltonianObjective(hamiltonian)

    qubits = ansatz.qubits

    if isinstance(hamiltonian, openfermion.DiagonalCoulombHamiltonian):
        one_body = hamiltonian.one_body
    elif isinstance(hamiltonian, openfermion.InteractionOperator):
        one_body = hamiltonian.one_body_tensor

    if isinstance(ansatz, SwapNetworkTrotterHubbardAnsatz):
        occupied_orbitals = (range(len(qubits)//4), range(len(qubits)//4))
    else:
        occupied_orbitals = range(len(qubits)//2)

    preparation_circuit = cirq.Circuit(
            prepare_gaussian_state(
                qubits,
                openfermion.QuadraticHamiltonian(one_body),
                occupied_orbitals=occupied_orbitals
            )
    )

    # Compute value using ansatz circuit and objective
    circuit = cirq.resolve_parameters(
            preparation_circuit + ansatz.circuit,
            ansatz.param_resolver(ansatz.default_initial_params()))
    result = circuit.final_wavefunction(
            qubit_order=ansatz.qubit_permutation(qubits))
    obj_val = objective.value(result)

    # Compute value using study
    study = VariationalStudy(
            'study',
            ansatz,
            objective,
            preparation_circuit=preparation_circuit)
    study_val = study.value_of(ansatz.default_initial_params())

    # Compute value by simulating time evolution
    if isinstance(hamiltonian, openfermion.DiagonalCoulombHamiltonian):
        half_way_hamiltonian = openfermion.DiagonalCoulombHamiltonian(
                one_body=hamiltonian.one_body,
                two_body=0.5 * hamiltonian.two_body)
    elif isinstance(hamiltonian, openfermion.InteractionOperator):
        half_way_hamiltonian = openfermion.InteractionOperator(
                constant=hamiltonian.constant,
                one_body_tensor=hamiltonian.one_body_tensor,
                two_body_tensor=0.5 * hamiltonian.two_body_tensor)

    simulation_circuit = cirq.Circuit(
            simulate_trotter(
                qubits,
                half_way_hamiltonian,
                time=ansatz.adiabatic_evolution_time,
                n_steps=1,
                order=order,
                algorithm=trotter_algorithm)
    )
    final_state = (
            preparation_circuit + simulation_circuit).final_wavefunction()
    correct_val = openfermion.expectation(
            objective._hamiltonian_linear_op, final_state).real

    numpy.testing.assert_allclose(obj_val, study_val, atol=atol)
    numpy.testing.assert_allclose(obj_val, correct_val, atol=atol)


@pytest.mark.parametrize(
        'ansatz, trotter_algorithm, order, hamiltonian, atol', [
    (SwapNetworkTrotterAnsatz(diag_coul_hamiltonian, iterations=2),
        LINEAR_SWAP_NETWORK, 1, diag_coul_hamiltonian, 5e-5),
    (SplitOperatorTrotterAnsatz(diag_coul_hamiltonian, iterations=2),
        SPLIT_OPERATOR, 1, diag_coul_hamiltonian, 5e-5),
    (LowRankTrotterAnsatz(h2_hamiltonian, iterations=2),
        LOW_RANK, 0, h2_hamiltonian, 5e-5),
    (LowRankTrotterAnsatz(lih_hamiltonian, iterations=2, final_rank=3),
        LowRankTrotterAlgorithm(final_rank=3), 0, lih_hamiltonian, 1e-3),
    (SwapNetworkTrotterHubbardAnsatz(2, 2, 1.0, 4.0, iterations=2),
        LINEAR_SWAP_NETWORK, 1,
        openfermion.get_diagonal_coulomb_hamiltonian(
            openfermion.reorder(
                openfermion.fermi_hubbard(2, 2, 1.0, 4.0),
                openfermion.up_then_down)
        ),
        5e-5)
])
def test_trotter_ansatzes_default_initial_params_iterations_2(
        ansatz, trotter_algorithm, order, hamiltonian, atol):
    """Check that a Trotter ansatz with two iterations and default parameters
    is consistent with time evolution with two Trotter steps."""

    objective = HamiltonianObjective(hamiltonian)

    qubits = ansatz.qubits

    if isinstance(hamiltonian, openfermion.DiagonalCoulombHamiltonian):
        one_body = hamiltonian.one_body
    elif isinstance(hamiltonian, openfermion.InteractionOperator):
        one_body = hamiltonian.one_body_tensor

    if isinstance(ansatz, SwapNetworkTrotterHubbardAnsatz):
        occupied_orbitals = (range(len(qubits)//4), range(len(qubits)//4))
    else:
        occupied_orbitals = range(len(qubits)//2)

    preparation_circuit = cirq.Circuit(
            prepare_gaussian_state(
                qubits,
                openfermion.QuadraticHamiltonian(one_body),
                occupied_orbitals=occupied_orbitals
            )
    )

    # Compute value using ansatz circuit and objective
    circuit = cirq.resolve_parameters(
            preparation_circuit + ansatz.circuit,
            ansatz.param_resolver(ansatz.default_initial_params()))
    result = circuit.final_wavefunction(
            qubit_order=ansatz.qubit_permutation(qubits))
    obj_val = objective.value(result)

    # Compute value using study
    study = VariationalStudy(
            'study',
            ansatz,
            objective,
            preparation_circuit=preparation_circuit)
    study_val = study.value_of(ansatz.default_initial_params())

    # Compute value by simulating time evolution
    if isinstance(hamiltonian, openfermion.DiagonalCoulombHamiltonian):
        quarter_way_hamiltonian = openfermion.DiagonalCoulombHamiltonian(
                one_body=hamiltonian.one_body,
                two_body=0.25 * hamiltonian.two_body)
        three_quarters_way_hamiltonian = openfermion.DiagonalCoulombHamiltonian(
                one_body=hamiltonian.one_body,
                two_body=0.75 * hamiltonian.two_body)
    elif isinstance(hamiltonian, openfermion.InteractionOperator):
        quarter_way_hamiltonian = openfermion.InteractionOperator(
                constant=hamiltonian.constant,
                one_body_tensor=hamiltonian.one_body_tensor,
                two_body_tensor=0.25 * hamiltonian.two_body_tensor)
        three_quarters_way_hamiltonian = openfermion.InteractionOperator(
                constant=hamiltonian.constant,
                one_body_tensor=hamiltonian.one_body_tensor,
                two_body_tensor=0.75 * hamiltonian.two_body_tensor)

    simulation_circuit = cirq.Circuit(
            simulate_trotter(
                qubits,
                quarter_way_hamiltonian,
                time=0.5 * ansatz.adiabatic_evolution_time,
                n_steps=1,
                order=order,
                algorithm=trotter_algorithm),
            simulate_trotter(
                qubits,
                three_quarters_way_hamiltonian,
                time=0.5 * ansatz.adiabatic_evolution_time,
                n_steps=1,
                order=order,
                algorithm=trotter_algorithm)
    )
    final_state = (
            preparation_circuit + simulation_circuit).final_wavefunction()
    correct_val = openfermion.expectation(
            objective._hamiltonian_linear_op, final_state).real

    numpy.testing.assert_allclose(obj_val, study_val, atol=atol)
    numpy.testing.assert_allclose(obj_val, correct_val, atol=atol)

[((1096, 1169), 'openfermion.random_diagonal_coulomb_hamiltonian', 'openfermion.random_diagonal_coulomb_hamiltonian', (['(4)'], {'real': '(True)', 'seed': '(47141)'}), '(4, real=True, seed=47141)\n', (1143, 1169), False, 'import openfermion\n'), ((2856, 2889), 'openfermioncirq.HamiltonianObjective', 'HamiltonianObjective', (['hamiltonian'], {}), '(hamiltonian)\n', (2876, 2889), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((3969, 4059), 'openfermioncirq.VariationalStudy', 'VariationalStudy', (['"""study"""', 'ansatz', 'objective'], {'preparation_circuit': 'preparation_circuit'}), "('study', ansatz, objective, preparation_circuit=\n    preparation_circuit)\n", (3985, 4059), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((5267, 5327), 'numpy.testing.assert_allclose', 'numpy.testing.assert_allclose', (['obj_val', 'study_val'], {'atol': 'atol'}), '(obj_val, study_val, atol=atol)\n', (5296, 5327), False, 'import numpy\n'), ((5332, 5394), 'numpy.testing.assert_allclose', 'numpy.testing.assert_allclose', (['obj_val', 'correct_val'], {'atol': 'atol'}), '(obj_val, correct_val, atol=atol)\n', (5361, 5394), False, 'import numpy\n'), ((6593, 6626), 'openfermioncirq.HamiltonianObjective', 'HamiltonianObjective', (['hamiltonian'], {}), '(hamiltonian)\n', (6613, 6626), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((7706, 7796), 'openfermioncirq.VariationalStudy', 'VariationalStudy', (['"""study"""', 'ansatz', 'objective'], {'preparation_circuit': 'preparation_circuit'}), "('study', ansatz, objective, preparation_circuit=\n    preparation_circuit)\n", (7722, 7796), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((9717, 9777), 'numpy.testing.assert_allclose', 'numpy.testing.assert_allclose', (['obj_val', 'study_val'], {'atol': 'atol'}), '(obj_val, study_val, atol=atol)\n', (9746, 9777), False, 'import numpy\n'), ((9782, 9844), 'numpy.testing.assert_allclose', 'numpy.testing.assert_allclose', (['obj_val', 'correct_val'], {'atol': 'atol'}), '(obj_val, correct_val, atol=atol)\n', (9811, 9844), False, 'import numpy\n'), ((4321, 4431), 'openfermion.DiagonalCoulombHamiltonian', 'openfermion.DiagonalCoulombHamiltonian', ([], {'one_body': 'hamiltonian.one_body', 'two_body': '(0.5 * hamiltonian.two_body)'}), '(one_body=hamiltonian.one_body,\n    two_body=0.5 * hamiltonian.two_body)\n', (4359, 4431), False, 'import openfermion\n'), ((4819, 4966), 'openfermioncirq.simulate_trotter', 'simulate_trotter', (['qubits', 'half_way_hamiltonian'], {'time': 'ansatz.adiabatic_evolution_time', 'n_steps': '(1)', 'order': 'order', 'algorithm': 'trotter_algorithm'}), '(qubits, half_way_hamiltonian, time=ansatz.\n    adiabatic_evolution_time, n_steps=1, order=order, algorithm=\n    trotter_algorithm)\n', (4835, 4966), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((5173, 5243), 'openfermion.expectation', 'openfermion.expectation', (['objective._hamiltonian_linear_op', 'final_state'], {}), '(objective._hamiltonian_linear_op, final_state)\n', (5196, 5243), False, 'import openfermion\n'), ((8061, 8172), 'openfermion.DiagonalCoulombHamiltonian', 'openfermion.DiagonalCoulombHamiltonian', ([], {'one_body': 'hamiltonian.one_body', 'two_body': '(0.25 * hamiltonian.two_body)'}), '(one_body=hamiltonian.one_body,\n    two_body=0.25 * hamiltonian.two_body)\n', (8099, 8172), False, 'import openfermion\n'), ((8243, 8354), 'openfermion.DiagonalCoulombHamiltonian', 'openfermion.DiagonalCoulombHamiltonian', ([], {'one_body': 'hamiltonian.one_body', 'two_body': '(0.75 * hamiltonian.two_body)'}), '(one_body=hamiltonian.one_body,\n    two_body=0.75 * hamiltonian.two_body)\n', (8281, 8354), False, 'import openfermion\n'), ((8996, 9152), 'openfermioncirq.simulate_trotter', 'simulate_trotter', (['qubits', 'quarter_way_hamiltonian'], {'time': '(0.5 * ansatz.adiabatic_evolution_time)', 'n_steps': '(1)', 'order': 'order', 'algorithm': 'trotter_algorithm'}), '(qubits, quarter_way_hamiltonian, time=0.5 * ansatz.\n    adiabatic_evolution_time, n_steps=1, order=order, algorithm=\n    trotter_algorithm)\n', (9012, 9152), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((9253, 9416), 'openfermioncirq.simulate_trotter', 'simulate_trotter', (['qubits', 'three_quarters_way_hamiltonian'], {'time': '(0.5 * ansatz.adiabatic_evolution_time)', 'n_steps': '(1)', 'order': 'order', 'algorithm': 'trotter_algorithm'}), '(qubits, three_quarters_way_hamiltonian, time=0.5 * ansatz.\n    adiabatic_evolution_time, n_steps=1, order=order, algorithm=\n    trotter_algorithm)\n', (9269, 9416), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((9623, 9693), 'openfermion.expectation', 'openfermion.expectation', (['objective._hamiltonian_linear_op', 'final_state'], {}), '(objective._hamiltonian_linear_op, final_state)\n', (9646, 9693), False, 'import openfermion\n'), ((3458, 3500), 'openfermion.QuadraticHamiltonian', 'openfermion.QuadraticHamiltonian', (['one_body'], {}), '(one_body)\n', (3490, 3500), False, 'import openfermion\n'), ((4559, 4725), 'openfermion.InteractionOperator', 'openfermion.InteractionOperator', ([], {'constant': 'hamiltonian.constant', 'one_body_tensor': 'hamiltonian.one_body_tensor', 'two_body_tensor': '(0.5 * hamiltonian.two_body_tensor)'}), '(constant=hamiltonian.constant,\n    one_body_tensor=hamiltonian.one_body_tensor, two_body_tensor=0.5 *\n    hamiltonian.two_body_tensor)\n', (4590, 4725), False, 'import openfermion\n'), ((1758, 1819), 'openfermioncirq.SwapNetworkTrotterAnsatz', 'SwapNetworkTrotterAnsatz', (['diag_coul_hamiltonian'], {'iterations': '(1)'}), '(diag_coul_hamiltonian, iterations=1)\n', (1782, 1819), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((1888, 1951), 'openfermioncirq.SplitOperatorTrotterAnsatz', 'SplitOperatorTrotterAnsatz', (['diag_coul_hamiltonian'], {'iterations': '(1)'}), '(diag_coul_hamiltonian, iterations=1)\n', (1914, 1951), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((2015, 2065), 'openfermioncirq.LowRankTrotterAnsatz', 'LowRankTrotterAnsatz', (['h2_hamiltonian'], {'iterations': '(1)'}), '(h2_hamiltonian, iterations=1)\n', (2035, 2065), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((2116, 2181), 'openfermioncirq.LowRankTrotterAnsatz', 'LowRankTrotterAnsatz', (['lih_hamiltonian'], {'iterations': '(1)', 'final_rank': '(3)'}), '(lih_hamiltonian, iterations=1, final_rank=3)\n', (2136, 2181), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((2191, 2228), 'openfermioncirq.trotter.LowRankTrotterAlgorithm', 'LowRankTrotterAlgorithm', ([], {'final_rank': '(3)'}), '(final_rank=3)\n', (2214, 2228), False, 'from openfermioncirq.trotter import LINEAR_SWAP_NETWORK, LOW_RANK, LowRankTrotterAlgorithm, SPLIT_OPERATOR\n'), ((2262, 2323), 'openfermioncirq.SwapNetworkTrotterHubbardAnsatz', 'SwapNetworkTrotterHubbardAnsatz', (['(2)', '(2)', '(1.0)', '(4.0)'], {'iterations': '(1)'}), '(2, 2, 1.0, 4.0, iterations=1)\n', (2293, 2323), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((7195, 7237), 'openfermion.QuadraticHamiltonian', 'openfermion.QuadraticHamiltonian', (['one_body'], {}), '(one_body)\n', (7227, 7237), False, 'import openfermion\n'), ((8485, 8652), 'openfermion.InteractionOperator', 'openfermion.InteractionOperator', ([], {'constant': 'hamiltonian.constant', 'one_body_tensor': 'hamiltonian.one_body_tensor', 'two_body_tensor': '(0.25 * hamiltonian.two_body_tensor)'}), '(constant=hamiltonian.constant,\n    one_body_tensor=hamiltonian.one_body_tensor, two_body_tensor=0.25 *\n    hamiltonian.two_body_tensor)\n', (8516, 8652), False, 'import openfermion\n'), ((8735, 8902), 'openfermion.InteractionOperator', 'openfermion.InteractionOperator', ([], {'constant': 'hamiltonian.constant', 'one_body_tensor': 'hamiltonian.one_body_tensor', 'two_body_tensor': '(0.75 * hamiltonian.two_body_tensor)'}), '(constant=hamiltonian.constant,\n    one_body_tensor=hamiltonian.one_body_tensor, two_body_tensor=0.75 *\n    hamiltonian.two_body_tensor)\n', (8766, 8902), False, 'import openfermion\n'), ((5493, 5554), 'openfermioncirq.SwapNetworkTrotterAnsatz', 'SwapNetworkTrotterAnsatz', (['diag_coul_hamiltonian'], {'iterations': '(2)'}), '(diag_coul_hamiltonian, iterations=2)\n', (5517, 5554), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((5623, 5686), 'openfermioncirq.SplitOperatorTrotterAnsatz', 'SplitOperatorTrotterAnsatz', (['diag_coul_hamiltonian'], {'iterations': '(2)'}), '(diag_coul_hamiltonian, iterations=2)\n', (5649, 5686), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((5750, 5800), 'openfermioncirq.LowRankTrotterAnsatz', 'LowRankTrotterAnsatz', (['h2_hamiltonian'], {'iterations': '(2)'}), '(h2_hamiltonian, iterations=2)\n', (5770, 5800), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((5851, 5916), 'openfermioncirq.LowRankTrotterAnsatz', 'LowRankTrotterAnsatz', (['lih_hamiltonian'], {'iterations': '(2)', 'final_rank': '(3)'}), '(lih_hamiltonian, iterations=2, final_rank=3)\n', (5871, 5916), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((5926, 5963), 'openfermioncirq.trotter.LowRankTrotterAlgorithm', 'LowRankTrotterAlgorithm', ([], {'final_rank': '(3)'}), '(final_rank=3)\n', (5949, 5963), False, 'from openfermioncirq.trotter import LINEAR_SWAP_NETWORK, LOW_RANK, LowRankTrotterAlgorithm, SPLIT_OPERATOR\n'), ((5997, 6058), 'openfermioncirq.SwapNetworkTrotterHubbardAnsatz', 'SwapNetworkTrotterHubbardAnsatz', (['(2)', '(2)', '(1.0)', '(4.0)'], {'iterations': '(2)'}), '(2, 2, 1.0, 4.0, iterations=2)\n', (6028, 6058), False, 'from openfermioncirq import HamiltonianObjective, LowRankTrotterAnsatz, SplitOperatorTrotterAnsatz, SwapNetworkTrotterAnsatz, SwapNetworkTrotterHubbardAnsatz, VariationalStudy, prepare_gaussian_state, simulate_trotter\n'), ((2460, 2501), 'openfermion.fermi_hubbard', 'openfermion.fermi_hubbard', (['(2)', '(2)', '(1.0)', '(4.0)'], {}), '(2, 2, 1.0, 4.0)\n', (2485, 2501), False, 'import openfermion\n'), ((6195, 6236), 'openfermion.fermi_hubbard', 'openfermion.fermi_hubbard', (['(2)', '(2)', '(1.0)', '(4.0)'], {}), '(2, 2, 1.0, 4.0)\n', (6220, 6236), False, 'import openfermion\n')]