# pylint: disable=wrong-or-nonexistent-copyright-notice
import itertools
import math

import numpy as np
import pytest
import sympy

import cirq
import cirq.contrib.quimb as ccq
import cirq.testing
from cirq import value


def assert_same_output_as_dense(circuit, qubit_order, initial_state=0, grouping=None):
    mps_simulator = ccq.mps_simulator.MPSSimulator(grouping=grouping)
    ref_simulator = cirq.Simulator()

    actual = mps_simulator.simulate(circuit, qubit_order=qubit_order, initial_state=initial_state)
    expected = ref_simulator.simulate(circuit, qubit_order=qubit_order, initial_state=initial_state)
    np.testing.assert_allclose(
        actual.final_state.to_numpy(), expected.final_state_vector, atol=1e-4
    )
    assert len(actual.measurements) == 0


def test_various_gates_1d():
    gate_op_cls = [cirq.I, cirq.H, cirq.X, cirq.Y, cirq.Z, cirq.T]
    cross_gate_op_cls = [cirq.CNOT, cirq.SWAP]

    q0, q1 = cirq.LineQubit.range(2)

    for q0_gate_op in gate_op_cls:
        for q1_gate_op in gate_op_cls:
            for cross_gate_op in cross_gate_op_cls:
                circuit = cirq.Circuit(q0_gate_op(q0), q1_gate_op(q1), cross_gate_op(q0, q1))
                for initial_state in range(2 * 2):
                    assert_same_output_as_dense(
                        circuit=circuit, qubit_order=[q0, q1], initial_state=initial_state
                    )


def test_various_gates_1d_flip():
    q0, q1 = cirq.LineQubit.range(2)

    circuit = cirq.Circuit(cirq.H(q1), cirq.CNOT(q1, q0))

    assert_same_output_as_dense(circuit=circuit, qubit_order=[q0, q1])
    assert_same_output_as_dense(circuit=circuit, qubit_order=[q1, q0])


def test_various_gates_2d():
    gate_op_cls = [cirq.I, cirq.H]
    cross_gate_op_cls = [cirq.CNOT, cirq.SWAP]

    q0, q1, q2, q3, q4, q5 = cirq.GridQubit.rect(3, 2)

    for q0_gate_op in gate_op_cls:
        for q1_gate_op in gate_op_cls:
            for q2_gate_op in gate_op_cls:
                for q3_gate_op in gate_op_cls:
                    for cross_gate_op1 in cross_gate_op_cls:
                        for cross_gate_op2 in cross_gate_op_cls:
                            circuit = cirq.Circuit(
                                q0_gate_op(q0),
                                q1_gate_op(q1),
                                cross_gate_op1(q0, q1),
                                q2_gate_op(q2),
                                q3_gate_op(q3),
                                cross_gate_op2(q3, q1),
                            )
                            assert_same_output_as_dense(
                                circuit=circuit, qubit_order=[q0, q1, q2, q3, q4, q5]
                            )


def test_grouping():
    q0, q1, q2 = cirq.LineQubit.range(3)

    circuit = cirq.Circuit(
        cirq.X(q0) ** 0.1,
        cirq.Y(q1) ** 0.2,
        cirq.Z(q2) ** 0.3,
        cirq.CNOT(q0, q1),
        cirq.Y(q1) ** 0.4,
    )

    groupings = [
        None,
        {q0: 0, q1: 1, q2: 2},
        {q0: 0, q1: 0, q2: 1},
        {q0: 0, q1: 1, q2: 0},
        {q0: 1, q1: 0, q2: 0},
        {q0: 0, q1: 0, q2: 0},
    ]

    for grouping in groupings:
        for initial_state in range(2 * 2 * 2):
            assert_same_output_as_dense(
                circuit=circuit,
                qubit_order=[q0, q1, q2],
                initial_state=initial_state,
                grouping=grouping,
            )


def test_grouping_does_not_overlap():
    q0, q1 = cirq.LineQubit.range(2)
    mps_simulator = ccq.mps_simulator.MPSSimulator(grouping={q0: 0})

    with pytest.raises(ValueError, match="Grouping must cover exactly the qubits"):
        mps_simulator.simulate(cirq.Circuit(), qubit_order={q0: 0, q1: 1})


def test_same_partial_trace():
    qubit_order = cirq.LineQubit.range(2)
    q0, q1 = qubit_order

    mps_simulator = ccq.mps_simulator.MPSSimulator()

    for _ in range(50):
        for initial_state in range(4):
            circuit = cirq.testing.random_circuit(qubit_order, 3, 0.9)
            expected_density_matrix = cirq.final_density_matrix(
                circuit, qubit_order=qubit_order, initial_state=initial_state
            )
            expected_partial_trace = cirq.partial_trace(
                expected_density_matrix.reshape(2, 2, 2, 2), keep_indices=[0]
            )

            final_state = mps_simulator.simulate(
                circuit, qubit_order=qubit_order, initial_state=initial_state
            ).final_state
            actual_density_matrix = final_state.partial_trace([q0, q1])
            actual_partial_trace = final_state.partial_trace([q0])

            np.testing.assert_allclose(actual_density_matrix, expected_density_matrix, atol=1e-4)
            np.testing.assert_allclose(actual_partial_trace, expected_partial_trace, atol=1e-4)


def test_probs_dont_sum_up_to_one():
    q0 = cirq.NamedQid('q0', dimension=2)
    circuit = cirq.Circuit(cirq.measure(q0))

    simulator = ccq.mps_simulator.MPSSimulator(
        simulation_options=ccq.mps_simulator.MPSOptions(sum_prob_atol=-0.5)
    )

    with pytest.raises(ValueError, match="Sum of probabilities exceeds tolerance"):
        simulator.run(circuit, repetitions=1)


def test_empty():
    q0 = cirq.NamedQid('q0', dimension=2)
    q1 = cirq.NamedQid('q1', dimension=3)
    q2 = cirq.NamedQid('q2', dimension=5)
    circuit = cirq.Circuit()

    for initial_state in range(2 * 3 * 5):
        assert_same_output_as_dense(
            circuit=circuit, qubit_order=[q0, q1, q2], initial_state=initial_state
        )


def test_cnot():
    q0, q1 = cirq.LineQubit.range(2)
    circuit = cirq.Circuit(cirq.CNOT(q0, q1))

    for initial_state in range(4):
        assert_same_output_as_dense(
            circuit=circuit, qubit_order=[q0, q1], initial_state=initial_state
        )


def test_cnot_flipped():
    q0, q1 = cirq.LineQubit.range(2)
    circuit = cirq.Circuit(cirq.CNOT(q1, q0))

    for initial_state in range(4):
        assert_same_output_as_dense(
            circuit=circuit, qubit_order=[q0, q1], initial_state=initial_state
        )


def test_simulation_state():
    q0, q1 = qubit_order = cirq.LineQubit.range(2)
    circuit = cirq.Circuit(cirq.CNOT(q1, q0))
    mps_simulator = ccq.mps_simulator.MPSSimulator()
    ref_simulator = cirq.Simulator()
    for initial_state in range(4):
        args = mps_simulator._create_simulation_state(initial_state=initial_state, qubits=(q0, q1))
        actual = mps_simulator.simulate(circuit, qubit_order=qubit_order, initial_state=args)
        expected = ref_simulator.simulate(
            circuit, qubit_order=qubit_order, initial_state=initial_state
        )
        np.testing.assert_allclose(
            actual.final_state.to_numpy(), expected.final_state_vector, atol=1e-4
        )
        assert len(actual.measurements) == 0


def test_three_qubits():
    q0, q1, q2 = cirq.LineQubit.range(3)
    circuit = cirq.Circuit(cirq.CCX(q0, q1, q2))

    with pytest.raises(ValueError, match="Can only handle 1 and 2 qubit operations"):
        assert_same_output_as_dense(circuit=circuit, qubit_order=[q0, q1, q2])


def test_measurement_1qubit():
    q0, q1 = cirq.LineQubit.range(2)
    circuit = cirq.Circuit(cirq.X(q0), cirq.H(q1), cirq.measure(q1))

    simulator = ccq.mps_simulator.MPSSimulator()

    result = simulator.run(circuit, repetitions=100)
    assert sum(result.measurements['q(1)'])[0] < 80
    assert sum(result.measurements['q(1)'])[0] > 20


def test_reset():
    q = cirq.LineQubit(0)
    simulator = ccq.mps_simulator.MPSSimulator()
    c = cirq.Circuit(cirq.X(q), cirq.reset(q), cirq.measure(q))
    assert simulator.sample(c)['q(0)'][0] == 0
    c = cirq.Circuit(cirq.H(q), cirq.reset(q), cirq.measure(q))
    assert simulator.sample(c)['q(0)'][0] == 0
    c = cirq.Circuit(cirq.reset(q), cirq.measure(q))
    assert simulator.sample(c)['q(0)'][0] == 0


def test_measurement_2qubits():
    q0, q1, q2 = cirq.LineQubit.range(3)
    circuit = cirq.Circuit(cirq.H(q0), cirq.H(q1), cirq.H(q2), cirq.measure(q0, q2))

    simulator = ccq.mps_simulator.MPSSimulator()

    repetitions = 1024
    measurement = simulator.run(circuit, repetitions=repetitions).measurements['q(0),q(2)']

    result_counts = {'00': 0, '01': 0, '10': 0, '11': 0}
    for i in range(repetitions):
        key = str(measurement[i, 0]) + str(measurement[i, 1])
        result_counts[key] += 1

    for result_count in result_counts.values():
        # Expected value is 1/4:
        assert result_count > repetitions * 0.15
        assert result_count < repetitions * 0.35


def test_measurement_str():
    q0 = cirq.NamedQid('q0', dimension=3)
    circuit = cirq.Circuit(cirq.measure(q0))

    simulator = ccq.mps_simulator.MPSSimulator()
    result = simulator.run(circuit, repetitions=7)

    assert str(result) == "q0 (d=3)=0000000"


def test_trial_result_str():
    q0 = cirq.LineQubit(0)
    final_simulator_state = ccq.mps_simulator.MPSState(
        qubits=(q0,),
        prng=value.parse_random_state(0),
        simulation_options=ccq.mps_simulator.MPSOptions(),
    )
    result = ccq.mps_simulator.MPSTrialResult(
        params=cirq.ParamResolver({}),
        measurements={'m': np.array([[1]])},
        final_simulator_state=final_simulator_state,
    )
    assert 'output state: TensorNetwork' in str(result)


def test_trial_result_repr_pretty():
    q0 = cirq.LineQubit(0)
    final_simulator_state = ccq.mps_simulator.MPSState(
        qubits=(q0,),
        prng=value.parse_random_state(0),
        simulation_options=ccq.mps_simulator.MPSOptions(),
    )
    result = ccq.mps_simulator.MPSTrialResult(
        params=cirq.ParamResolver({}),
        measurements={'m': np.array([[1]])},
        final_simulator_state=final_simulator_state,
    )
    cirq.testing.assert_repr_pretty_contains(result, 'output state: TensorNetwork')
    cirq.testing.assert_repr_pretty(result, "cirq.MPSTrialResult(...)", cycle=True)


def test_empty_step_result():
    q0 = cirq.LineQubit(0)
    sim = ccq.mps_simulator.MPSSimulator()
    step_result = next(sim.simulate_moment_steps(cirq.Circuit(cirq.measure(q0))))
    assert 'TensorNetwork' in str(step_result)


def test_step_result_repr_pretty():
    q0 = cirq.LineQubit(0)
    sim = ccq.mps_simulator.MPSSimulator()
    step_result = next(sim.simulate_moment_steps(cirq.Circuit(cirq.measure(q0))))
    cirq.testing.assert_repr_pretty_contains(step_result, 'TensorNetwork')
    cirq.testing.assert_repr_pretty(step_result, "cirq.MPSSimulatorStepResult(...)", cycle=True)


def test_state_equal():
    q0, q1 = cirq.LineQubit.range(2)
    state0 = ccq.mps_simulator.MPSState(
        qubits=(q0,),
        prng=value.parse_random_state(0),
        simulation_options=ccq.mps_simulator.MPSOptions(cutoff=1e-3, sum_prob_atol=1e-3),
    )
    state1a = ccq.mps_simulator.MPSState(
        qubits=(q1,),
        prng=value.parse_random_state(0),
        simulation_options=ccq.mps_simulator.MPSOptions(cutoff=1e-3, sum_prob_atol=1e-3),
    )
    state1b = ccq.mps_simulator.MPSState(
        qubits=(q1,),
        prng=value.parse_random_state(0),
        simulation_options=ccq.mps_simulator.MPSOptions(cutoff=1729.0, sum_prob_atol=1e-3),
    )
    assert state0 == state0
    assert state0 != state1a
    assert state1a != state1b


def test_random_circuits_equal_more_rows():
    circuit = cirq.testing.random_circuit(
        qubits=cirq.GridQubit.rect(3, 2), n_moments=6, op_density=1.0
    )
    qubits = circuit.all_qubits()
    assert_same_output_as_dense(circuit, qubits)


def test_supremacy_equal_more_cols():
    circuit = cirq.testing.random_circuit(
        qubits=cirq.GridQubit.rect(2, 3), n_moments=6, op_density=1.0
    )
    qubits = circuit.all_qubits()
    assert_same_output_as_dense(circuit, qubits)


def test_tensor_index_names():
    qubits = cirq.LineQubit.range(12)
    qubit_map = {qubit: i for i, qubit in enumerate(qubits)}
    state = ccq.mps_simulator.MPSState(qubits=qubit_map, prng=value.parse_random_state(0))

    assert state.i_str(0) == "i_00"
    assert state.i_str(11) == "i_11"
    assert state.mu_str(0, 3) == "mu_0_3"
    assert state.mu_str(3, 0) == "mu_0_3"


def test_simulate_moment_steps_sample():
    q0, q1 = cirq.LineQubit.range(2)
    circuit = cirq.Circuit(cirq.H(q0), cirq.CNOT(q0, q1))

    simulator = ccq.mps_simulator.MPSSimulator()

    for i, step in enumerate(simulator.simulate_moment_steps(circuit)):
        if i == 0:
            np.testing.assert_almost_equal(
                step._simulator_state().to_numpy(),
                np.asarray([1.0 / math.sqrt(2), 0.0, 1.0 / math.sqrt(2), 0.0]),
            )
            # There are two "Tensor()" copies in the string.
            assert len(str(step).split('Tensor(')) == 3
            samples = step.sample([q0, q1], repetitions=10)
            for sample in samples:
                assert np.array_equal(sample, [True, False]) or np.array_equal(
                    sample, [False, False]
                )
            np.testing.assert_almost_equal(
                step._simulator_state().to_numpy(),
                np.asarray([1.0 / math.sqrt(2), 0.0, 1.0 / math.sqrt(2), 0.0]),
            )
        else:
            np.testing.assert_almost_equal(
                step._simulator_state().to_numpy(),
                np.asarray([1.0 / math.sqrt(2), 0.0, 0.0, 1.0 / math.sqrt(2)]),
            )
            # There are two "Tensor()" copies in the string.
            assert len(str(step).split('Tensor(')) == 3
            samples = step.sample([q0, q1], repetitions=10)
            for sample in samples:
                assert np.array_equal(sample, [True, True]) or np.array_equal(
                    sample, [False, False]
                )


def test_sample_seed():
    q = cirq.NamedQubit('q')
    circuit = cirq.Circuit(cirq.H(q), cirq.measure(q))
    simulator = ccq.mps_simulator.MPSSimulator(seed=1234)
    result = simulator.run(circuit, repetitions=20)
    measured = result.measurements['q']
    result_string = ''.join(map(lambda x: str(int(x[0])), measured))
    assert result_string == '01011001110111011011'


def test_run_no_repetitions():
    q0 = cirq.LineQubit(0)
    simulator = ccq.mps_simulator.MPSSimulator()
    circuit = cirq.Circuit(cirq.H(q0), cirq.measure(q0))
    result = simulator.run(circuit, repetitions=0)
    assert len(result.measurements['q(0)']) == 0


def test_run_parameters_not_resolved():
    a = cirq.LineQubit(0)
    simulator = ccq.mps_simulator.MPSSimulator()
    circuit = cirq.Circuit(cirq.XPowGate(exponent=sympy.Symbol('a'))(a), cirq.measure(a))
    with pytest.raises(ValueError, match='symbols were not specified'):
        _ = simulator.run_sweep(circuit, cirq.ParamResolver({}))


def test_deterministic_gate_noise():
    q = cirq.LineQubit(0)
    circuit = cirq.Circuit(cirq.I(q), cirq.measure(q))

    simulator1 = ccq.mps_simulator.MPSSimulator(noise=cirq.X)
    result1 = simulator1.run(circuit, repetitions=10)

    simulator2 = ccq.mps_simulator.MPSSimulator(noise=cirq.X)
    result2 = simulator2.run(circuit, repetitions=10)

    assert result1 == result2

    simulator3 = ccq.mps_simulator.MPSSimulator(noise=cirq.Z)
    result3 = simulator3.run(circuit, repetitions=10)

    assert result1 != result3


def test_nondeterministic_mixture_noise():
    q = cirq.LineQubit(0)
    circuit = cirq.Circuit(cirq.I(q), cirq.measure(q))

    simulator = ccq.mps_simulator.MPSSimulator(
        noise=cirq.ConstantQubitNoiseModel(cirq.depolarize(0.5))
    )
    result1 = simulator.run(circuit, repetitions=50)
    result2 = simulator.run(circuit, repetitions=50)

    assert result1 != result2


def test_unsupported_noise_fails():
    with pytest.raises(ValueError, match='noise must be unitary or mixture but was'):
        ccq.mps_simulator.MPSSimulator(noise=cirq.amplitude_damp(0.5))


def test_state_copy():
    sim = ccq.mps_simulator.MPSSimulator()

    q = cirq.LineQubit(0)
    circuit = cirq.Circuit(cirq.H(q), cirq.H(q))

    state_Ms = []
    for step in sim.simulate_moment_steps(circuit):
        state_Ms.append(step.state.M)
    for x, y in itertools.combinations(state_Ms, 2):
        assert len(x) == len(y)
        for i in range(len(x)):
            assert not np.shares_memory(x[i], y[i])


def test_simulation_state_initializer():
    s = ccq.mps_simulator.MPSState(
        qubits=(cirq.LineQubit(0),),
        prng=np.random.RandomState(0),
        classical_data=cirq.ClassicalDataDictionaryStore(
            _records={cirq.MeasurementKey('test'): [(4,)]}
        ),
    )
    assert s.qubits == (cirq.LineQubit(0),)
    assert s.log_of_measurement_results == {'test': [4]}


def test_act_on_gate():
    args = ccq.mps_simulator.MPSState(qubits=cirq.LineQubit.range(3), prng=np.random.RandomState(0))

    cirq.act_on(cirq.X, args, [cirq.LineQubit(1)])
    np.testing.assert_allclose(
        args.state_vector().reshape((2, 2, 2)),
        cirq.one_hot(index=(0, 1, 0), shape=(2, 2, 2), dtype=np.complex64),
    )


def test_deprecated():
    prng = np.random.RandomState(0)
    with cirq.testing.assert_deprecated('log_of_measurement_results', deadline='0.16', count=2):
        _ = ccq.mps_simulator.MPSState(
            qubits=cirq.LineQubit.range(3), prng=prng, log_of_measurement_results={}
        )
    with cirq.testing.assert_deprecated('positional', deadline='0.16'):
        _ = ccq.mps_simulator.MPSState(cirq.LineQubit.range(3), prng=prng)

[((16, 20, 16, 69), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', (), '', True, 'import cirq.contrib.quimb as ccq\n'), ((17, 20, 17, 36), 'cirq.Simulator', 'cirq.Simulator', ({}, {}), '()', False, 'import cirq\n'), ((31, 13, 31, 36), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(31, 34, 31, 35): '2'}, {}), '(2)', False, 'import cirq\n'), ((44, 13, 44, 36), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(44, 34, 44, 35): '2'}, {}), '(2)', False, 'import cirq\n'), ((56, 29, 56, 54), 'cirq.GridQubit.rect', 'cirq.GridQubit.rect', ({(56, 49, 56, 50): '3', (56, 52, 56, 53): '2'}, {}), '(3, 2)', False, 'import cirq\n'), ((78, 17, 78, 40), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(78, 38, 78, 39): '3'}, {}), '(3)', False, 'import cirq\n'), ((108, 13, 108, 36), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(108, 34, 108, 35): '2'}, {}), '(2)', False, 'import cirq\n'), ((109, 20, 109, 68), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', (), '', True, 'import cirq.contrib.quimb as ccq\n'), ((116, 18, 116, 41), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(116, 39, 116, 40): '2'}, {}), '(2)', False, 'import cirq\n'), ((119, 20, 119, 52), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((142, 9, 142, 41), 'cirq.NamedQid', 'cirq.NamedQid', (), '', False, 'import cirq\n'), ((154, 9, 154, 41), 'cirq.NamedQid', 'cirq.NamedQid', (), '', False, 'import cirq\n'), ((155, 9, 155, 41), 'cirq.NamedQid', 'cirq.NamedQid', (), '', False, 'import cirq\n'), ((156, 9, 156, 41), 'cirq.NamedQid', 'cirq.NamedQid', (), '', False, 'import cirq\n'), ((157, 14, 157, 28), 'cirq.Circuit', 'cirq.Circuit', ({}, {}), '()', False, 'import cirq\n'), ((166, 13, 166, 36), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(166, 34, 166, 35): '2'}, {}), '(2)', False, 'import cirq\n'), ((176, 13, 176, 36), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(176, 34, 176, 35): '2'}, {}), '(2)', False, 'import cirq\n'), ((186, 27, 186, 50), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(186, 48, 186, 49): '2'}, {}), '(2)', False, 'import cirq\n'), ((188, 20, 188, 52), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((189, 20, 189, 36), 'cirq.Simulator', 'cirq.Simulator', ({}, {}), '()', False, 'import cirq\n'), ((203, 17, 203, 40), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(203, 38, 203, 39): '3'}, {}), '(3)', False, 'import cirq\n'), ((211, 13, 211, 36), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(211, 34, 211, 35): '2'}, {}), '(2)', False, 'import cirq\n'), ((214, 16, 214, 48), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((222, 8, 222, 25), 'cirq.LineQubit', 'cirq.LineQubit', ({(222, 23, 222, 24): '0'}, {}), '(0)', False, 'import cirq\n'), ((223, 16, 223, 48), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((233, 17, 233, 40), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(233, 38, 233, 39): '3'}, {}), '(3)', False, 'import cirq\n'), ((236, 16, 236, 48), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((253, 9, 253, 41), 'cirq.NamedQid', 'cirq.NamedQid', (), '', False, 'import cirq\n'), ((256, 16, 256, 48), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((263, 9, 263, 26), 'cirq.LineQubit', 'cirq.LineQubit', ({(263, 24, 263, 25): '0'}, {}), '(0)', False, 'import cirq\n'), ((278, 9, 278, 26), 'cirq.LineQubit', 'cirq.LineQubit', ({(278, 24, 278, 25): '0'}, {}), '(0)', False, 'import cirq\n'), ((289, 4, 289, 83), 'cirq.testing.assert_repr_pretty_contains', 'cirq.testing.assert_repr_pretty_contains', ({(289, 45, 289, 51): 'result', (289, 53, 289, 82): '"""output state: TensorNetwork"""'}, {}), "(result, 'output state: TensorNetwork')", False, 'import cirq\n'), ((290, 4, 290, 83), 'cirq.testing.assert_repr_pretty', 'cirq.testing.assert_repr_pretty', (), '', False, 'import cirq\n'), ((294, 9, 294, 26), 'cirq.LineQubit', 'cirq.LineQubit', ({(294, 24, 294, 25): '0'}, {}), '(0)', False, 'import cirq\n'), ((295, 10, 295, 42), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((301, 9, 301, 26), 'cirq.LineQubit', 'cirq.LineQubit', ({(301, 24, 301, 25): '0'}, {}), '(0)', False, 'import cirq\n'), ((302, 10, 302, 42), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((304, 4, 304, 74), 'cirq.testing.assert_repr_pretty_contains', 'cirq.testing.assert_repr_pretty_contains', ({(304, 45, 304, 56): 'step_result', (304, 58, 304, 73): '"""TensorNetwork"""'}, {}), "(step_result, 'TensorNetwork')", False, 'import cirq\n'), ((305, 4, 305, 96), 'cirq.testing.assert_repr_pretty', 'cirq.testing.assert_repr_pretty', (), '', False, 'import cirq\n'), ((309, 13, 309, 36), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(309, 34, 309, 35): '2'}, {}), '(2)', False, 'import cirq\n'), ((347, 13, 347, 37), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(347, 34, 347, 36): '12'}, {}), '(12)', False, 'import cirq\n'), ((358, 13, 358, 36), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(358, 34, 358, 35): '2'}, {}), '(2)', False, 'import cirq\n'), ((361, 16, 361, 48), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((395, 8, 395, 28), 'cirq.NamedQubit', 'cirq.NamedQubit', ({(395, 24, 395, 27): '"""q"""'}, {}), "('q')", False, 'import cirq\n'), ((397, 16, 397, 57), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', (), '', True, 'import cirq.contrib.quimb as ccq\n'), ((405, 9, 405, 26), 'cirq.LineQubit', 'cirq.LineQubit', ({(405, 24, 405, 25): '0'}, {}), '(0)', False, 'import cirq\n'), ((406, 16, 406, 48), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((413, 8, 413, 25), 'cirq.LineQubit', 'cirq.LineQubit', ({(413, 23, 413, 24): '0'}, {}), '(0)', False, 'import cirq\n'), ((414, 16, 414, 48), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((421, 8, 421, 25), 'cirq.LineQubit', 'cirq.LineQubit', ({(421, 23, 421, 24): '0'}, {}), '(0)', False, 'import cirq\n'), ((424, 17, 424, 61), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', (), '', True, 'import cirq.contrib.quimb as ccq\n'), ((427, 17, 427, 61), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', (), '', True, 'import cirq.contrib.quimb as ccq\n'), ((432, 17, 432, 61), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', (), '', True, 'import cirq.contrib.quimb as ccq\n'), ((439, 8, 439, 25), 'cirq.LineQubit', 'cirq.LineQubit', ({(439, 23, 439, 24): '0'}, {}), '(0)', False, 'import cirq\n'), ((457, 10, 457, 42), 'cirq.contrib.quimb.mps_simulator.MPSSimulator', 'ccq.mps_simulator.MPSSimulator', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((459, 8, 459, 25), 'cirq.LineQubit', 'cirq.LineQubit', ({(459, 23, 459, 24): '0'}, {}), '(0)', False, 'import cirq\n'), ((465, 16, 465, 51), 'itertools.combinations', 'itertools.combinations', ({(465, 39, 465, 47): 'state_Ms', (465, 49, 465, 50): '(2)'}, {}), '(state_Ms, 2)', False, 'import itertools\n'), ((494, 11, 494, 35), 'numpy.random.RandomState', 'np.random.RandomState', ({(494, 33, 494, 34): '0'}, {}), '(0)', True, 'import numpy as np\n'), ((46, 27, 46, 37), 'cirq.H', 'cirq.H', ({(46, 34, 46, 36): 'q1'}, {}), '(q1)', False, 'import cirq\n'), ((46, 39, 46, 56), 'cirq.CNOT', 'cirq.CNOT', ({(46, 49, 46, 51): 'q1', (46, 53, 46, 55): 'q0'}, {}), '(q1, q0)', False, 'import cirq\n'), ((84, 8, 84, 25), 'cirq.CNOT', 'cirq.CNOT', ({(84, 18, 84, 20): 'q0', (84, 22, 84, 24): 'q1'}, {}), '(q0, q1)', False, 'import cirq\n'), ((111, 9, 111, 82), 'pytest.raises', 'pytest.raises', (), '', False, 'import pytest\n'), ((143, 27, 143, 43), 'cirq.measure', 'cirq.measure', ({(143, 40, 143, 42): 'q0'}, {}), '(q0)', False, 'import cirq\n'), ((149, 9, 149, 82), 'pytest.raises', 'pytest.raises', (), '', False, 'import pytest\n'), ((167, 27, 167, 44), 'cirq.CNOT', 'cirq.CNOT', ({(167, 37, 167, 39): 'q0', (167, 41, 167, 43): 'q1'}, {}), '(q0, q1)', False, 'import cirq\n'), ((177, 27, 177, 44), 'cirq.CNOT', 'cirq.CNOT', ({(177, 37, 177, 39): 'q1', (177, 41, 177, 43): 'q0'}, {}), '(q1, q0)', False, 'import cirq\n'), ((187, 27, 187, 44), 'cirq.CNOT', 'cirq.CNOT', ({(187, 37, 187, 39): 'q1', (187, 41, 187, 43): 'q0'}, {}), '(q1, q0)', False, 'import cirq\n'), ((204, 27, 204, 47), 'cirq.CCX', 'cirq.CCX', ({(204, 36, 204, 38): 'q0', (204, 40, 204, 42): 'q1', (204, 44, 204, 46): 'q2'}, {}), '(q0, q1, q2)', False, 'import cirq\n'), ((206, 9, 206, 84), 'pytest.raises', 'pytest.raises', (), '', False, 'import pytest\n'), ((212, 27, 212, 37), 'cirq.X', 'cirq.X', ({(212, 34, 212, 36): 'q0'}, {}), '(q0)', False, 'import cirq\n'), ((212, 39, 212, 49), 'cirq.H', 'cirq.H', ({(212, 46, 212, 48): 'q1'}, {}), '(q1)', False, 'import cirq\n'), ((212, 51, 212, 67), 'cirq.measure', 'cirq.measure', ({(212, 64, 212, 66): 'q1'}, {}), '(q1)', False, 'import cirq\n'), ((224, 21, 224, 30), 'cirq.X', 'cirq.X', ({(224, 28, 224, 29): 'q'}, {}), '(q)', False, 'import cirq\n'), ((224, 32, 224, 45), 'cirq.reset', 'cirq.reset', ({(224, 43, 224, 44): 'q'}, {}), '(q)', False, 'import cirq\n'), ((224, 47, 224, 62), 'cirq.measure', 'cirq.measure', ({(224, 60, 224, 61): 'q'}, {}), '(q)', False, 'import cirq\n'), ((226, 21, 226, 30), 'cirq.H', 'cirq.H', ({(226, 28, 226, 29): 'q'}, {}), '(q)', False, 'import cirq\n'), ((226, 32, 226, 45), 'cirq.reset', 'cirq.reset', ({(226, 43, 226, 44): 'q'}, {}), '(q)', False, 'import cirq\n'), ((226, 47, 226, 62), 'cirq.measure', 'cirq.measure', ({(226, 60, 226, 61): 'q'}, {}), '(q)', False, 'import cirq\n'), ((228, 21, 228, 34), 'cirq.reset', 'cirq.reset', ({(228, 32, 228, 33): 'q'}, {}), '(q)', False, 'import cirq\n'), ((228, 36, 228, 51), 'cirq.measure', 'cirq.measure', ({(228, 49, 228, 50): 'q'}, {}), '(q)', False, 'import cirq\n'), ((234, 27, 234, 37), 'cirq.H', 'cirq.H', ({(234, 34, 234, 36): 'q0'}, {}), '(q0)', False, 'import cirq\n'), ((234, 39, 234, 49), 'cirq.H', 'cirq.H', ({(234, 46, 234, 48): 'q1'}, {}), '(q1)', False, 'import cirq\n'), ((234, 51, 234, 61), 'cirq.H', 'cirq.H', ({(234, 58, 234, 60): 'q2'}, {}), '(q2)', False, 'import cirq\n'), ((234, 63, 234, 83), 'cirq.measure', 'cirq.measure', ({(234, 76, 234, 78): 'q0', (234, 80, 234, 82): 'q2'}, {}), '(q0, q2)', False, 'import cirq\n'), ((254, 27, 254, 43), 'cirq.measure', 'cirq.measure', ({(254, 40, 254, 42): 'q0'}, {}), '(q0)', False, 'import cirq\n'), ((359, 27, 359, 37), 'cirq.H', 'cirq.H', ({(359, 34, 359, 36): 'q0'}, {}), '(q0)', False, 'import cirq\n'), ((359, 39, 359, 56), 'cirq.CNOT', 'cirq.CNOT', ({(359, 49, 359, 51): 'q0', (359, 53, 359, 55): 'q1'}, {}), '(q0, q1)', False, 'import cirq\n'), ((396, 27, 396, 36), 'cirq.H', 'cirq.H', ({(396, 34, 396, 35): 'q'}, {}), '(q)', False, 'import cirq\n'), ((396, 38, 396, 53), 'cirq.measure', 'cirq.measure', ({(396, 51, 396, 52): 'q'}, {}), '(q)', False, 'import cirq\n'), ((407, 27, 407, 37), 'cirq.H', 'cirq.H', ({(407, 34, 407, 36): 'q0'}, {}), '(q0)', False, 'import cirq\n'), ((407, 39, 407, 55), 'cirq.measure', 'cirq.measure', ({(407, 52, 407, 54): 'q0'}, {}), '(q0)', False, 'import cirq\n'), ((415, 73, 415, 88), 'cirq.measure', 'cirq.measure', ({(415, 86, 415, 87): 'a'}, {}), '(a)', False, 'import cirq\n'), ((416, 9, 416, 70), 'pytest.raises', 'pytest.raises', (), '', False, 'import pytest\n'), ((422, 27, 422, 36), 'cirq.I', 'cirq.I', ({(422, 34, 422, 35): 'q'}, {}), '(q)', False, 'import cirq\n'), ((422, 38, 422, 53), 'cirq.measure', 'cirq.measure', ({(422, 51, 422, 52): 'q'}, {}), '(q)', False, 'import cirq\n'), ((440, 27, 440, 36), 'cirq.I', 'cirq.I', ({(440, 34, 440, 35): 'q'}, {}), '(q)', False, 'import cirq\n'), ((440, 38, 440, 53), 'cirq.measure', 'cirq.measure', ({(440, 51, 440, 52): 'q'}, {}), '(q)', False, 'import cirq\n'), ((452, 9, 452, 84), 'pytest.raises', 'pytest.raises', (), '', False, 'import pytest\n'), ((460, 27, 460, 36), 'cirq.H', 'cirq.H', ({(460, 34, 460, 35): 'q'}, {}), '(q)', False, 'import cirq\n'), ((460, 38, 460, 47), 'cirq.H', 'cirq.H', ({(460, 45, 460, 46): 'q'}, {}), '(q)', False, 'import cirq\n'), ((489, 8, 489, 74), 'cirq.one_hot', 'cirq.one_hot', (), '', False, 'import cirq\n'), ((495, 9, 495, 95), 'cirq.testing.assert_deprecated', 'cirq.testing.assert_deprecated', (), '', False, 'import cirq\n'), ((499, 9, 499, 70), 'cirq.testing.assert_deprecated', 'cirq.testing.assert_deprecated', (), '', False, 'import cirq\n'), ((81, 8, 81, 18), 'cirq.X', 'cirq.X', ({(81, 15, 81, 17): 'q0'}, {}), '(q0)', False, 'import cirq\n'), ((82, 8, 82, 18), 'cirq.Y', 'cirq.Y', ({(82, 15, 82, 17): 'q1'}, {}), '(q1)', False, 'import cirq\n'), ((83, 8, 83, 18), 'cirq.Z', 'cirq.Z', ({(83, 15, 83, 17): 'q2'}, {}), '(q2)', False, 'import cirq\n'), ((85, 8, 85, 18), 'cirq.Y', 'cirq.Y', ({(85, 15, 85, 17): 'q1'}, {}), '(q1)', False, 'import cirq\n'), ((112, 31, 112, 45), 'cirq.Circuit', 'cirq.Circuit', ({}, {}), '()', False, 'import cirq\n'), ((123, 22, 123, 70), 'cirq.testing.random_circuit', 'cirq.testing.random_circuit', ({(123, 50, 123, 61): 'qubit_order', (123, 63, 123, 64): '3', (123, 66, 123, 69): '0.9'}, {}), '(qubit_order, 3, 0.9)', False, 'import cirq\n'), ((124, 38, 126, 13), 'cirq.final_density_matrix', 'cirq.final_density_matrix', (), '', False, 'import cirq\n'), ((137, 12, 137, 97), 'numpy.testing.assert_allclose', 'np.testing.assert_allclose', (), '', True, 'import numpy as np\n'), ((138, 12, 138, 95), 'numpy.testing.assert_allclose', 'np.testing.assert_allclose', (), '', True, 'import numpy as np\n'), ((146, 27, 146, 75), 'cirq.contrib.quimb.mps_simulator.MPSOptions', 'ccq.mps_simulator.MPSOptions', (), '', True, 'import cirq.contrib.quimb as ccq\n'), ((266, 13, 266, 40), 'cirq.value.parse_random_state', 'value.parse_random_state', ({(266, 38, 266, 39): '0'}, {}), '(0)', False, 'from cirq import value\n'), ((267, 27, 267, 57), 'cirq.contrib.quimb.mps_simulator.MPSOptions', 'ccq.mps_simulator.MPSOptions', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((270, 15, 270, 37), 'cirq.ParamResolver', 'cirq.ParamResolver', ({(270, 34, 270, 36): '{}'}, {}), '({})', False, 'import cirq\n'), ((281, 13, 281, 40), 'cirq.value.parse_random_state', 'value.parse_random_state', ({(281, 38, 281, 39): '0'}, {}), '(0)', False, 'from cirq import value\n'), ((282, 27, 282, 57), 'cirq.contrib.quimb.mps_simulator.MPSOptions', 'ccq.mps_simulator.MPSOptions', ({}, {}), '()', True, 'import cirq.contrib.quimb as ccq\n'), ((285, 15, 285, 37), 'cirq.ParamResolver', 'cirq.ParamResolver', ({(285, 34, 285, 36): '{}'}, {}), '({})', False, 'import cirq\n'), ((312, 13, 312, 40), 'cirq.value.parse_random_state', 'value.parse_random_state', ({(312, 38, 312, 39): '0'}, {}), '(0)', False, 'from cirq import value\n'), ((313, 27, 313, 88), 'cirq.contrib.quimb.mps_simulator.MPSOptions', 'ccq.mps_simulator.MPSOptions', (), '', True, 'import cirq.contrib.quimb as ccq\n'), ((317, 13, 317, 40), 'cirq.value.parse_random_state', 'value.parse_random_state', ({(317, 38, 317, 39): '0'}, {}), '(0)', False, 'from cirq import value\n'), ((318, 27, 318, 88), 'cirq.contrib.quimb.mps_simulator.MPSOptions', 'ccq.mps_simulator.MPSOptions', (), '', True, 'import cirq.contrib.quimb as ccq\n'), ((322, 13, 322, 40), 'cirq.value.parse_random_state', 'value.parse_random_state', ({(322, 38, 322, 39): '0'}, {}), '(0)', False, 'from cirq import value\n'), ((323, 27, 323, 90), 'cirq.contrib.quimb.mps_simulator.MPSOptions', 'ccq.mps_simulator.MPSOptions', (), '', True, 'import cirq.contrib.quimb as ccq\n'), ((332, 15, 332, 40), 'cirq.GridQubit.rect', 'cirq.GridQubit.rect', ({(332, 35, 332, 36): '3', (332, 38, 332, 39): '2'}, {}), '(3, 2)', False, 'import cirq\n'), ((340, 15, 340, 40), 'cirq.GridQubit.rect', 'cirq.GridQubit.rect', ({(340, 35, 340, 36): '2', (340, 38, 340, 39): '3'}, {}), '(2, 3)', False, 'import cirq\n'), ((349, 62, 349, 89), 'cirq.value.parse_random_state', 'value.parse_random_state', ({(349, 87, 349, 88): '0'}, {}), '(0)', False, 'from cirq import value\n'), ((417, 41, 417, 63), 'cirq.ParamResolver', 'cirq.ParamResolver', ({(417, 60, 417, 62): '{}'}, {}), '({})', False, 'import cirq\n'), ((474, 13, 474, 37), 'numpy.random.RandomState', 'np.random.RandomState', ({(474, 35, 474, 36): '0'}, {}), '(0)', True, 'import numpy as np\n'), ((479, 24, 479, 41), 'cirq.LineQubit', 'cirq.LineQubit', ({(479, 39, 479, 40): '(0)'}, {}), '(0)', False, 'import cirq\n'), ((484, 45, 484, 68), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(484, 66, 484, 67): '3'}, {}), '(3)', False, 'import cirq\n'), ((484, 75, 484, 99), 'numpy.random.RandomState', 'np.random.RandomState', ({(484, 97, 484, 98): '0'}, {}), '(0)', True, 'import numpy as np\n'), ((486, 31, 486, 48), 'cirq.LineQubit', 'cirq.LineQubit', ({(486, 46, 486, 47): '(1)'}, {}), '(1)', False, 'import cirq\n'), ((500, 39, 500, 62), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(500, 60, 500, 61): '3'}, {}), '(3)', False, 'import cirq\n'), ((271, 27, 271, 42), 'numpy.array', 'np.array', ({(271, 36, 271, 41): '[[1]]'}, {}), '([[1]])', True, 'import numpy as np\n'), ((286, 27, 286, 42), 'numpy.array', 'np.array', ({(286, 36, 286, 41): '[[1]]'}, {}), '([[1]])', True, 'import numpy as np\n'), ((296, 62, 296, 78), 'cirq.measure', 'cirq.measure', ({(296, 75, 296, 77): 'q0'}, {}), '(q0)', False, 'import cirq\n'), ((303, 62, 303, 78), 'cirq.measure', 'cirq.measure', ({(303, 75, 303, 77): 'q0'}, {}), '(q0)', False, 'import cirq\n'), ((443, 43, 443, 63), 'cirq.depolarize', 'cirq.depolarize', ({(443, 59, 443, 62): '0.5'}, {}), '(0.5)', False, 'import cirq\n'), ((453, 45, 453, 69), 'cirq.amplitude_damp', 'cirq.amplitude_damp', ({(453, 65, 453, 68): '(0.5)'}, {}), '(0.5)', False, 'import cirq\n'), ((468, 23, 468, 51), 'numpy.shares_memory', 'np.shares_memory', ({(468, 40, 468, 44): 'x[i]', (468, 46, 468, 50): 'y[i]'}, {}), '(x[i], y[i])', True, 'import numpy as np\n'), ((473, 16, 473, 33), 'cirq.LineQubit', 'cirq.LineQubit', ({(473, 31, 473, 32): '0'}, {}), '(0)', False, 'import cirq\n'), ((497, 19, 497, 42), 'cirq.LineQubit.range', 'cirq.LineQubit.range', ({(497, 40, 497, 41): '3'}, {}), '(3)', False, 'import cirq\n'), ((373, 23, 373, 60), 'numpy.array_equal', 'np.array_equal', ({(373, 38, 373, 44): 'sample', (373, 46, 373, 59): '[True, False]'}, {}), '(sample, [True, False])', True, 'import numpy as np\n'), ((373, 64, 375, 17), 'numpy.array_equal', 'np.array_equal', ({(374, 20, 374, 26): 'sample', (374, 28, 374, 42): '[False, False]'}, {}), '(sample, [False, False])', True, 'import numpy as np\n'), ((389, 23, 389, 59), 'numpy.array_equal', 'np.array_equal', ({(389, 38, 389, 44): 'sample', (389, 46, 389, 58): '[True, True]'}, {}), '(sample, [True, True])', True, 'import numpy as np\n'), ((389, 63, 391, 17), 'numpy.array_equal', 'np.array_equal', ({(390, 20, 390, 26): 'sample', (390, 28, 390, 42): '[False, False]'}, {}), '(sample, [False, False])', True, 'import numpy as np\n'), ((415, 50, 415, 67), 'sympy.Symbol', 'sympy.Symbol', ({(415, 63, 415, 66): '"""a"""'}, {}), "('a')", False, 'import sympy\n'), ((476, 22, 476, 49), 'cirq.MeasurementKey', 'cirq.MeasurementKey', ({(476, 42, 476, 48): '"""test"""'}, {}), "('test')", False, 'import cirq\n'), ((367, 34, 367, 46), 'math.sqrt', 'math.sqrt', ({(367, 44, 367, 45): '(2)'}, {}), '(2)', False, 'import math\n'), ((367, 59, 367, 71), 'math.sqrt', 'math.sqrt', ({(367, 69, 367, 70): '(2)'}, {}), '(2)', False, 'import math\n'), ((378, 34, 378, 46), 'math.sqrt', 'math.sqrt', ({(378, 44, 378, 45): '(2)'}, {}), '(2)', False, 'import math\n'), ((378, 59, 378, 71), 'math.sqrt', 'math.sqrt', ({(378, 69, 378, 70): '(2)'}, {}), '(2)', False, 'import math\n'), ((383, 34, 383, 46), 'math.sqrt', 'math.sqrt', ({(383, 44, 383, 45): '(2)'}, {}), '(2)', False, 'import math\n'), ((383, 64, 383, 76), 'math.sqrt', 'math.sqrt', ({(383, 74, 383, 75): '(2)'}, {}), '(2)', False, 'import math\n')]