Пример #1
0
def test_circuit_to_choi():
    """Tests _circuit_to_choi is consistent with _operation_to_choi."""
    base_noise = 0.01
    q = LineQubit(0)
    noisy_operation = depolarize(base_noise).on(q)
    assert np.allclose(
        _operation_to_choi(noisy_operation),
        _circuit_to_choi(Circuit(noisy_operation)),
    )
    noisy_sequence = [noisy_operation, noisy_operation]
    assert np.allclose(
        _operation_to_choi(noisy_sequence),
        _circuit_to_choi(Circuit(noisy_sequence)),
    )
Пример #2
0
def test_sample_sequence_choi(gate: cirq.Gate):
    """Tests the sample_sequence by comparing the exact Choi matrices."""
    qreg = cirq.LineQubit.range(gate.num_qubits())
    ideal_op = gate.on(*qreg)
    ideal_circ = cirq.Circuit(ideal_op)
    noisy_op_tree = [ideal_op] + [cirq.depolarize(BASE_NOISE)(q) for q in qreg]

    ideal_choi = _operation_to_choi(ideal_op)
    noisy_choi = _operation_to_choi(noisy_op_tree)

    representation = represent_operation_with_local_depolarizing_noise(
        ideal_circ,
        BASE_NOISE,
    )

    choi_unbiased_estimates = []
    rng = np.random.RandomState(1)
    for _ in range(500):
        imp_seqs, signs, norm = sample_sequence(ideal_circ, [representation],
                                                random_state=rng)
        noisy_sequence = imp_seqs[0].with_noise(cirq.depolarize(BASE_NOISE))
        sequence_choi = _circuit_to_choi(noisy_sequence)
        choi_unbiased_estimates.append(norm * signs[0] * sequence_choi)

    choi_pec_estimate = np.average(choi_unbiased_estimates, axis=0)
    noise_error = np.linalg.norm(ideal_choi - noisy_choi)
    pec_error = np.linalg.norm(ideal_choi - choi_pec_estimate)

    assert pec_error < noise_error
    assert np.allclose(ideal_choi, choi_pec_estimate, atol=0.05)
Пример #3
0
def test_amplitude_damping_representation_with_choi(
    gate: Gate,
    noise: float,
    circuit_type: str,
):
    """Tests the representation by comparing exact Choi matrices."""
    q = LineQubit(0)
    ideal_circuit = convert_from_mitiq(Circuit(gate.on(q)), circuit_type)
    ideal_choi = _circuit_to_choi(Circuit(gate.on(q)))
    op_rep = _represent_operation_with_amplitude_damping_noise(
        ideal_circuit,
        noise,
    )
    choi_components = []
    for noisy_op, coeff in op_rep.basis_expansion.items():
        implementable_circ = noisy_op.circuit()
        depolarizing_op = AmplitudeDampingChannel(noise).on(q)
        # Apply noise after each sequence.
        # NOTE: noise is not applied after each operation.
        implementable_circ.append(depolarizing_op)
        sequence_choi = _operation_to_choi(implementable_circ)
        choi_components.append(coeff * sequence_choi)

    combination_choi = np.sum(choi_components, axis=0)
    assert np.allclose(ideal_choi, combination_choi, atol=10**-8)
Пример #4
0
def test_biased_noise_representation_with_choi(
    gate: Gate, epsilon: float, eta: float
):
    """Tests the representation by comparing exact Choi matrices."""
    qreg = LineQubit.range(gate.num_qubits())
    ideal_choi = _operation_to_choi(gate.on(*qreg))
    op_rep = represent_operation_with_local_biased_noise(
        Circuit(gate.on(*qreg)), epsilon, eta
    )
    choi_components = []

    # Define biased noise channel
    a = 1 - epsilon
    b = epsilon * (3 * eta + 1) / (3 * (eta + 1))
    c = epsilon / (3 * (eta + 1))

    mix = [
        (a, unitary(I)),
        (b, unitary(Z)),
        (c, unitary(X)),
        (c, unitary(Y)),
    ]

    for noisy_op, coeff in op_rep.basis_expansion.items():
        implementable_circ = noisy_op.circuit()
        # Apply noise after each sequence.
        # NOTE: noise is not applied after each operation.
        biased_op = ops.MixedUnitaryChannel(mix).on_each(*qreg)
        implementable_circ.append(biased_op)
        sequence_choi = _circuit_to_choi(implementable_circ)
        choi_components.append(coeff * sequence_choi)
    combination_choi = np.sum(choi_components, axis=0)
    assert np.allclose(ideal_choi, combination_choi, atol=10**-6)
Пример #5
0
def test_sample_circuit_choi():
    """Tests the sample_circuit by comparing the exact Choi matrices."""
    # A simple 2-qubit circuit
    qreg = cirq.LineQubit.range(2)
    ideal_circ = cirq.Circuit(
        cirq.X.on(qreg[0]),
        cirq.I.on(qreg[1]),
        cirq.CNOT.on(*qreg),
    )

    noisy_circuit = ideal_circ.with_noise(cirq.depolarize(BASE_NOISE))

    ideal_choi = _circuit_to_choi(ideal_circ)
    noisy_choi = _operation_to_choi(noisy_circuit)

    rep_list = represent_operations_in_circuit_with_local_depolarizing_noise(
        ideal_circuit=ideal_circ,
        noise_level=BASE_NOISE,
    )

    choi_unbiased_estimates = []
    rng = np.random.RandomState(1)
    for _ in range(500):
        imp_circs, signs, norm = sample_circuit(ideal_circ,
                                                rep_list,
                                                random_state=rng)
        noisy_imp_circ = imp_circs[0].with_noise(cirq.depolarize(BASE_NOISE))
        sequence_choi = _circuit_to_choi(noisy_imp_circ)
        choi_unbiased_estimates.append(norm * signs[0] * sequence_choi)

    choi_pec_estimate = np.average(choi_unbiased_estimates, axis=0)
    noise_error = np.linalg.norm(ideal_choi - noisy_choi)
    pec_error = np.linalg.norm(ideal_choi - choi_pec_estimate)

    assert pec_error < noise_error
    assert np.allclose(ideal_choi, choi_pec_estimate, atol=0.05)
Пример #6
0
def test_find_optimal_representation_depolarizing_two_qubit_gates(circ_type):
    """Test optimal representation agrees with a known analytic result."""
    for ideal_gate, noise_level in product([CNOT, CZ], [0.1, 0.5]):
        q = LineQubit.range(2)
        ideal_op = Circuit(ideal_gate(*q))
        implementable_circuits = [Circuit(ideal_op)]
        # Append two-qubit-gate with Paulis on one qubit
        for gate in [X, Y, Z]:
            implementable_circuits.append(Circuit([ideal_op, gate(q[0])]))
            implementable_circuits.append(Circuit([ideal_op, gate(q[1])]))
        # Append two-qubit gate with Paulis on both qubits
        for gate_a, gate_b in product([X, Y, Z], repeat=2):
            implementable_circuits.append(
                Circuit([ideal_op, gate_a(q[0]), gate_b(q[1])])
            )
        noisy_circuits = [
            circ + Circuit(DepolarizingChannel(noise_level).on_each(*q))
            for circ in implementable_circuits
        ]
        super_operators = [
            choi_to_super(_circuit_to_choi(circ)) for circ in noisy_circuits
        ]

        # Define circuits with native types
        implementable_native = [
            convert_from_mitiq(c, circ_type) for c in implementable_circuits
        ]
        ideal_op_native = convert_from_mitiq(ideal_op, circ_type)

        noisy_operations = [
            NoisyOperation(ideal, real)
            for ideal, real in zip(implementable_native, super_operators)
        ]

        # Find optimal representation
        noisy_basis = NoisyBasis(*noisy_operations)
        rep = find_optimal_representation(
            ideal_op_native, noisy_basis, tol=1.0e-8
        )
        # Expected analytical result
        expected_rep = represent_operation_with_local_depolarizing_noise(
            ideal_op_native,
            noise_level,
        )
        assert np.allclose(np.sort(rep.coeffs), np.sort(expected_rep.coeffs))
        assert rep == expected_rep
Пример #7
0
def test_depolarizing_representation_with_choi(gate: Gate, noise: float):
    """Tests the representation by comparing exact Choi matrices."""
    qreg = LineQubit.range(gate.num_qubits())
    ideal_choi = _operation_to_choi(gate.on(*qreg))
    op_rep = represent_operation_with_global_depolarizing_noise(
        Circuit(gate.on(*qreg)), noise,
    )
    choi_components = []
    for noisy_op, coeff in op_rep.basis_expansion.items():
        implementable_circ = noisy_op.circuit()
        # Apply noise after each sequence.
        # NOTE: noise is not applied after each operation.
        depolarizing_op = DepolarizingChannel(noise, len(qreg))(*qreg)
        implementable_circ.append(depolarizing_op)
        sequence_choi = _circuit_to_choi(implementable_circ)
        choi_components.append(coeff * sequence_choi)
    combination_choi = np.sum(choi_components, axis=0)
    assert np.allclose(ideal_choi, combination_choi, atol=10 ** -6)
Пример #8
0
def test_find_optimal_representation_single_qubit_amp_damping(circ_type):
    """Test optimal representation of agrees with a known analytic result."""
    for ideal_gate, noise_level in product([X, Y, H], [0.1, 0.3]):
        q = LineQubit(0)

        ideal_op = Circuit(ideal_gate(q))
        implementable_circuits = [Circuit(ideal_op)]
        # Add ideal gate followed by Paulis and reset
        for gate in [Z, reset]:
            implementable_circuits.append(Circuit([ideal_op, gate(q)]))

        noisy_circuits = [
            circ + Circuit(AmplitudeDampingChannel(noise_level).on_each(q))
            for circ in implementable_circuits
        ]

        super_operators = [
            choi_to_super(_circuit_to_choi(circ)) for circ in noisy_circuits
        ]

        # Define circuits with native types
        implementable_native = [
            convert_from_mitiq(c, circ_type) for c in implementable_circuits
        ]
        ideal_op_native = convert_from_mitiq(ideal_op, circ_type)

        noisy_operations = [
            NoisyOperation(ideal, real)
            for ideal, real in zip(implementable_native, super_operators)
        ]
        # Find optimal representation
        noisy_basis = NoisyBasis(*noisy_operations)
        rep = find_optimal_representation(
            ideal_op_native, noisy_basis, tol=1.0e-7, initial_guess=[0, 0, 0]
        )
        # Expected analytical result
        expected_rep = _represent_operation_with_amplitude_damping_noise(
            ideal_op_native,
            noise_level,
        )
        assert np.allclose(np.sort(rep.coeffs), np.sort(expected_rep.coeffs))
        assert rep == expected_rep