Exemple #1
0
def test_trotter_ansatzes_default_initial_params_iterations_1(
        ansatz_factory, 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."""

    ansatz = ansatz_factory(hamiltonian, iterations=1)
    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

    preparation_circuit = cirq.Circuit.from_ops(
        prepare_gaussian_state(qubits,
                               openfermion.QuadraticHamiltonian(one_body),
                               occupied_orbitals=range(len(qubits) // 2)))

    # Compute value using ansatz circuit and objective
    circuit = (preparation_circuit +
               ansatz.circuit).with_parameters_resolved_by(
                   ansatz.param_resolver(ansatz.default_initial_params()))
    result = circuit.apply_unitary_effect_to_state(
        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.from_ops(
        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).apply_unitary_effect_to_state()
    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)
def test_trotter_ansatzes_evaluate_order_2(ansatz_factory, trotter_algorithm,
                                           hamiltonian, atol):
    """Check that a Trotter ansatz with two iterations and default parameters
    is consistent with time evolution with two Trotter steps."""

    ansatz = ansatz_factory(hamiltonian, iterations=2)
    qubits = ansatz.qubits

    preparation_circuit = cirq.Circuit.from_ops(
        prepare_gaussian_state(qubits,
                               openfermion.QuadraticHamiltonian(
                                   hamiltonian.one_body),
                               occupied_orbitals=range(len(qubits) // 2)))
    study = HamiltonianVariationalStudy(
        'study', ansatz, hamiltonian, preparation_circuit=preparation_circuit)

    simulator = cirq.google.XmonSimulator()

    # Compute value using ansatz
    val = study.evaluate(study.default_initial_params())

    # Compute value by simulating time evolution
    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)
    simulation_circuit = cirq.Circuit.from_ops(
        simulate_trotter(qubits,
                         quarter_way_hamiltonian,
                         time=0.5 * ansatz.adiabatic_evolution_time,
                         n_steps=1,
                         order=1,
                         algorithm=trotter_algorithm),
        simulate_trotter(qubits,
                         three_quarters_way_hamiltonian,
                         time=0.5 * ansatz.adiabatic_evolution_time,
                         n_steps=1,
                         order=1,
                         algorithm=trotter_algorithm))
    circuit = preparation_circuit + simulation_circuit
    result = simulator.simulate(circuit)
    final_state = result.final_state
    correct_val = openfermion.expectation(study._hamiltonian_linear_op,
                                          final_state).real

    numpy.testing.assert_allclose(val, correct_val, atol=atol)
def test_simulate_trotter_omit_final_swaps():
    n_qubits = 5
    qubits = cirq.LineQubit.range(n_qubits)
    hamiltonian = openfermion.DiagonalCoulombHamiltonian(
            one_body=numpy.ones((n_qubits, n_qubits)),
            two_body=numpy.ones((n_qubits, n_qubits)))
    time = 1.0

    circuit_with_swaps = cirq.Circuit.from_ops(
            simulate_trotter(
                qubits, hamiltonian, time, order=0,
                algorithm=LINEAR_SWAP_NETWORK))
    circuit_without_swaps = cirq.Circuit.from_ops(
            simulate_trotter(
                qubits, hamiltonian, time, order=0,
                algorithm=LINEAR_SWAP_NETWORK,
                omit_final_swaps=True))

    assert len(circuit_without_swaps) < len(circuit_with_swaps)

    circuit_with_swaps = cirq.Circuit.from_ops(
            simulate_trotter(
                qubits,
                hamiltonian,
                time,
                order=1,
                n_steps=3,
                algorithm=SPLIT_OPERATOR),
            strategy=cirq.InsertStrategy.NEW)
    circuit_without_swaps = cirq.Circuit.from_ops(
            simulate_trotter(
                qubits,
                hamiltonian,
                time,
                order=1,
                n_steps=3,
                algorithm=SPLIT_OPERATOR,
                omit_final_swaps=True),
            strategy=cirq.InsertStrategy.NEW)

    assert len(circuit_without_swaps) < len(circuit_with_swaps)

    hamiltonian = lih_hamiltonian
    qubits = cirq.LineQubit.range(4)
    circuit_with_swaps = cirq.Circuit.from_ops(
            simulate_trotter(
                qubits, hamiltonian, time, order=0,
                algorithm=LOW_RANK))
    circuit_without_swaps = cirq.Circuit.from_ops(
            simulate_trotter(
                qubits, hamiltonian, time, order=0,
                algorithm=LOW_RANK,
                omit_final_swaps=True))

    assert len(circuit_without_swaps) < len(circuit_with_swaps)
Exemple #4
0
    def as_diagonal_coulomb_hamiltonian(
            self) -> openfermion.DiagonalCoulombHamiltonian:
        """Exports Fermi Hubbard Hamiltonian as DiagonalCoulombHamiltonian.

        Returns: Description of Fermi Hubbard problem as
            openfermion.DiagonalCoulombHamiltonian.
        """
        def spin_map(j: int, spin: int) -> int:
            """Mapping from site and spin to index (separated in spin sectors).

            Assigns indices 0 through self.sites_count - 1 when spin = 0 and
            indices self.sites_count through 2 * self.sites_count - 1 when
            spin = 1.
            """
            return j + spin * self.sites_count

        modes = 2 * self.sites_count

        # Prepare one-body matrix T_ij.
        one_body = np.zeros((modes, modes))

        # Nearest-neighbor hopping terms.
        t = self.j_array
        for j, s in product(range(self.interactions_count), [0, 1]):
            j1 = (j + 1) % self.sites_count
            one_body[spin_map(j, s), spin_map(j1, s)] += -t[j]
            one_body[spin_map(j1, s), spin_map(j, s)] += -t[j]

        # Local interaction terms.
        local_up = self.local_up_array
        local_down = self.local_down_array
        for j in range(self.sites_count):
            one_body[spin_map(j, 0), spin_map(j, 0)] += local_up[j]
            one_body[spin_map(j, 1), spin_map(j, 1)] += local_down[j]

        # Prepare the two-body matrix V_ij.
        two_body = np.zeros((modes, modes))

        # On-site interaction terms.
        u = self.u_array
        for j in range(self.sites_count):
            two_body[spin_map(j, 0), spin_map(j, 1)] += u[j] / 2.
            two_body[spin_map(j, 1), spin_map(j, 0)] += u[j] / 2.

        # Nearest-neighbor interaction terms.
        v = self.v_array
        for j, (s0, s1) in product(range(self.interactions_count),
                                   np.ndindex((2, 2))):
            j1 = (j + 1) % self.sites_count
            two_body[spin_map(j, s0), spin_map(j1, s1)] += v[j] / 2.
            two_body[spin_map(j1, s1), spin_map(j, s0)] += v[j] / 2.

        return openfermion.DiagonalCoulombHamiltonian(one_body, two_body)
import numpy

import cirq
import openfermion

from openfermioncirq.variational.ansatzes import SwapNetworkTrotterAnsatz

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

# Construct an empty Hamiltonian
zero_hamiltonian = openfermion.DiagonalCoulombHamiltonian(one_body=numpy.zeros(
    (4, 4)),
                                                          two_body=numpy.zeros(
                                                              (4, 4)))


def test_swap_network_trotter_ansatz_params():

    ansatz = SwapNetworkTrotterAnsatz(hubbard_hamiltonian)
    assert (set(ansatz.params()) == {
        cirq.Symbol(name)
        for name in {
            'T_0_2_0', 'T_4_6_0', 'T_1_3_0', 'T_5_7_0', 'T_0_4_0', 'T_2_6_0',
            'T_1_5_0', 'T_3_7_0', 'V_0_1_0', 'V_2_3_0', 'V_4_5_0', 'V_6_7_0'
        }
    })

    ansatz = SwapNetworkTrotterAnsatz(hubbard_hamiltonian, iterations=2)
Exemple #6
0
#   See the License for the specific language governing permissions and
#   limitations under the License.

import numpy

import cirq
import openfermion

from openfermioncirq.trotter import SPLIT_OPERATOR

n_qubits = 4
qubits = cirq.LineQubit.range(n_qubits)
control = cirq.LineQubit(-1)
ones_hamiltonian = openfermion.DiagonalCoulombHamiltonian(one_body=numpy.ones(
    (n_qubits, n_qubits)),
                                                          two_body=numpy.ones(
                                                              (n_qubits,
                                                               n_qubits)),
                                                          constant=1.0)


def test_split_operator_trotter_step_symmetric():
    circuit = cirq.Circuit.from_ops(
        SPLIT_OPERATOR.symmetric(ones_hamiltonian).trotter_step(qubits, 1.0),
        strategy=cirq.InsertStrategy.EARLIEST)
    assert circuit.to_text_diagram(transpose=True).strip() == """
0        1          2           3
│        │          │           │
Z^-0.159 Z^-0.159   Z^-0.159    Z^-0.796
│        │          │           │
Z        Z^0.0      Z^0.0       Z^0.0
│        │          │           │
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 {
            'U_0_0', 'U_1_0', 'U_6_0', 'U_7_0', 'V_0_1_0', 'V_2_3_0',
            'V_4_5_0', 'V_6_7_0'
        }
    })

    ansatz = SplitOperatorTrotterAnsatz(hubbard_hamiltonian, iterations=2)
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)
Exemple #9
0
def test_simulate_trotter_omit_final_swaps():
    n_qubits = 5
    qubits = cirq.LineQubit.range(n_qubits)
    hamiltonian = openfermion.DiagonalCoulombHamiltonian(one_body=numpy.ones(
        (n_qubits, n_qubits)),
                                                         two_body=numpy.ones(
                                                             (n_qubits,
                                                              n_qubits)))
    time = 1.0

    circuit_with_swaps = cirq.Circuit.from_ops(
        simulate_trotter(qubits,
                         hamiltonian,
                         time,
                         order=0,
                         algorithm=LINEAR_SWAP_NETWORK))
    circuit_without_swaps = cirq.Circuit.from_ops(
        simulate_trotter(qubits,
                         hamiltonian,
                         time,
                         order=0,
                         algorithm=LINEAR_SWAP_NETWORK,
                         omit_final_swaps=True))

    assert (circuit_with_swaps.to_text_diagram(transpose=True).strip() == (
        circuit_without_swaps.to_text_diagram(transpose=True).strip() + """
│        ×ᶠ─────────×ᶠ         ×ᶠ─────────×ᶠ
│        │          │          │          │
×ᶠ───────×ᶠ         ×ᶠ─────────×ᶠ         │
│        │          │          │          │
│        ×ᶠ─────────×ᶠ         ×ᶠ─────────×ᶠ
│        │          │          │          │
×ᶠ───────×ᶠ         ×ᶠ─────────×ᶠ         │
│        │          │          │          │
│        ×ᶠ─────────×ᶠ         ×ᶠ─────────×ᶠ
│        │          │          │          │
""").strip())

    circuit_with_swaps = cirq.Circuit.from_ops(
        simulate_trotter(qubits,
                         hamiltonian,
                         time,
                         order=1,
                         n_steps=3,
                         algorithm=SPLIT_OPERATOR),
        strategy=cirq.InsertStrategy.NEW)
    circuit_without_swaps = cirq.Circuit.from_ops(
        simulate_trotter(qubits,
                         hamiltonian,
                         time,
                         order=1,
                         n_steps=3,
                         algorithm=SPLIT_OPERATOR,
                         omit_final_swaps=True),
        strategy=cirq.InsertStrategy.NEW)

    assert (circuit_with_swaps.to_text_diagram(transpose=True).strip() == (
        circuit_without_swaps.to_text_diagram(transpose=True).strip() + """
│         │           │           ×────────────×
│         │           │           │            │
│         ×───────────×           │            │
│         │           │           │            │
│         │           ×───────────×            │
│         │           │           │            │
×─────────×           │           │            │
│         │           │           │            │
│         │           │           ×────────────×
│         │           │           │            │
│         ×───────────×           │            │
│         │           │           │            │
│         │           ×───────────×            │
│         │           │           │            │
×─────────×           │           │            │
│         │           │           │            │
│         │           │           ×────────────×
│         │           │           │            │
│         ×───────────×           │            │
│         │           │           │            │
""").strip())

    hamiltonian = random_interaction_operator(n_qubits, seed=0)
    circuit_with_swaps = cirq.Circuit.from_ops(
        simulate_trotter(qubits,
                         hamiltonian,
                         time,
                         order=0,
                         algorithm=LOW_RANK))
    circuit_without_swaps = cirq.Circuit.from_ops(
        simulate_trotter(qubits,
                         hamiltonian,
                         time,
                         order=0,
                         algorithm=LOW_RANK,
                         omit_final_swaps=True))

    assert len(circuit_without_swaps) < len(circuit_with_swaps)