Пример #1
0
def test_print_operation_representation_two_qubits_neg():
    qreg = cirq.LineQubit.range(2)
    ideal = cirq.Circuit(cirq.CNOT(*qreg))

    noisy_a = NoisyOperation.from_cirq(
        circuit=cirq.Circuit(cirq.H.on_each(qreg[0]), cirq.CNOT(
            *qreg), cirq.H.on_each(qreg[1])))
    noisy_b = NoisyOperation.from_cirq(
        circuit=cirq.Circuit(cirq.Z.on_each(qreg[1])))
    decomp = OperationRepresentation(
        ideal=ideal,
        basis_expansion={
            noisy_a: -0.5,
            noisy_b: 1.5,
        },
    )
    print(str(decomp))
    expected = f"""
0: ───@───
      │
1: ───X─── ={" "}

-0.500
0: ───H───@───────
          │
1: ───────X───H───

+1.500
1: ───Z───"""
    # Remove initial newline
    expected = expected[1:]
    assert str(decomp) == expected
Пример #2
0
def test_on_each_bad_types():
    ideal = cirq.Circuit(cirq.I(cirq.LineQubit(0)))
    real = np.identity(4)
    with pytest.raises(TypeError, match="must be iterable"):
        NoisyOperation.on_each(ideal,
                               qubits=cirq.NamedQubit("new"),
                               channel_matrix=real)
Пример #3
0
def test_on_each_multiple_qubits_bad_qubits_shape():
    real_cnot = np.zeros(shape=(16, 16))
    qubits = [cirq.LineQubit.range(3)]
    with pytest.raises(
        ValueError, match="Number of qubits in each register should be"
    ):
        NoisyOperation.on_each(cirq.CNOT, qubits=qubits, real=real_cnot)
Пример #4
0
def test_transform_qubits_wrong_number():
    real = np.zeros(shape=(16, 16))
    qreg = [cirq.NamedQubit("Dummy 1"), cirq.NamedQubit("Dummy 2")]
    ideal = cirq.Circuit(cirq.ops.CNOT.on(*qreg))
    noisy_op = NoisyOperation(ideal, real)

    with pytest.raises(ValueError, match="Expected 2 qubits but received"):
        noisy_op.transform_qubits(qubits=[cirq.NamedQubit("new")])
Пример #5
0
def test_print_cirq_operation_representation():
    ideal = cirq.Circuit(cirq.H(cirq.LineQubit(0)))

    noisy_xop = NoisyOperation.from_cirq(circuit=cirq.X,
                                         channel_matrix=np.zeros(shape=(4, 4)))
    noisy_zop = NoisyOperation.from_cirq(circuit=cirq.Z,
                                         channel_matrix=np.zeros(shape=(4, 4)))
    # Positive first coefficient
    decomp = OperationRepresentation(
        ideal=ideal,
        basis_expansion={
            noisy_xop: 0.5,
            noisy_zop: 0.5,
        },
    )
    expected = r"0: ───H─── = 0.500*(0: ───X───)+0.500*(0: ───Z───)"
    assert str(decomp) == expected
    # Negative first coefficient
    decomp = OperationRepresentation(
        ideal=ideal,
        basis_expansion={
            noisy_xop: -0.5,
            noisy_zop: 1.5,
        },
    )
    expected = r"0: ───H─── = -0.500*(0: ───X───)+1.500*(0: ───Z───)"
    assert str(decomp) == expected
    # Empty representation
    decomp = OperationRepresentation(ideal=ideal, basis_expansion={})
    expected = r"0: ───H─── = 0.000"
    assert str(decomp) == expected
    # Small coefficient approximation
    decomp = OperationRepresentation(
        ideal=ideal,
        basis_expansion={
            noisy_xop: 1.00001,
            noisy_zop: 0.00001
        },
    )
    expected = r"0: ───H─── = 1.000*(0: ───X───)"
    assert str(decomp) == expected
    # Small coefficient approximation different position
    decomp = OperationRepresentation(
        ideal=ideal,
        basis_expansion={
            noisy_xop: 0.00001,
            noisy_zop: 1.00001
        },
    )
    expected = r"0: ───H─── = 1.000*(0: ───Z───)"
    # Small coefficient approximation different position
    decomp = OperationRepresentation(
        ideal=ideal,
        basis_expansion={noisy_xop: 0.00001},
    )
    expected = r"0: ───H─── = 0.000"
    assert str(decomp) == expected
Пример #6
0
def test_noisy_basis_add_bad_types():
    rng = np.random.RandomState(seed=1)
    noisy_basis = NoisyBasis(
        NoisyOperation.from_cirq(ideal=cirq.I, real=rng.rand(4, 4)),
        NoisyOperation.from_cirq(ideal=cirq.X, real=rng.rand(4, 4)),
    )

    with pytest.raises(TypeError, match="All basis elements must be of type"):
        noisy_basis.add(cirq.Y)
Пример #7
0
def test_add_noisy_operation_no_channel_matrix():
    noisy_op1 = NoisyOperation(cirq.Circuit([cirq.X.on(cirq.NamedQubit("Q"))]))
    noisy_op2 = NoisyOperation(
        cirq.Circuit([cirq.X.on(cirq.NamedQubit("Q"))]),
        channel_matrix=np.random.rand(4, 4),
    )

    with pytest.raises(ValueError):
        (noisy_op1 + noisy_op2).channel_matrix
Пример #8
0
def test_noisy_basis_simple():
    rng = np.random.RandomState(seed=1)
    noisy_basis = NoisyBasis(
        NoisyOperation.from_cirq(ideal=cirq.I, real=rng.rand(4, 4)),
        NoisyOperation.from_cirq(ideal=cirq.X, real=rng.rand(4, 4)),
        NoisyOperation.from_cirq(ideal=cirq.Y, real=rng.rand(4, 4)),
        NoisyOperation.from_cirq(ideal=cirq.Z, real=rng.rand(4, 4)),
    )
    assert len(noisy_basis) == 4
    assert noisy_basis.all_qubits() == {cirq.LineQubit(0)}
Пример #9
0
def test_extend_to_simple():
    rng = np.random.RandomState(seed=1)
    noisy_basis = NoisyBasis(
        NoisyOperation.from_cirq(ideal=cirq.I, real=rng.rand(4, 4)),
        NoisyOperation.from_cirq(ideal=cirq.X, real=rng.rand(4, 4)),
    )
    assert len(noisy_basis.elements) == 2

    noisy_basis.extend_to(cirq.LineQubit.range(1, 3))
    assert len(noisy_basis.elements) == 6
Пример #10
0
def test_init_with_cirq_circuit():
    qreg = cirq.LineQubit.range(2)
    circ = cirq.Circuit(cirq.H.on(qreg[0]), cirq.CNOT.on(*qreg))
    real = np.zeros(shape=(16, 16))
    noisy_op = NoisyOperation(circ, real)

    assert isinstance(noisy_op._ideal, cirq.Circuit)
    assert _equal(noisy_op.ideal_circuit(), circ, require_qubit_equality=True)
    assert set(noisy_op.qubits) == set(qreg)
    assert np.allclose(noisy_op.ideal_unitary, cirq.unitary(circ))
    assert np.allclose(noisy_op.real_matrix, real)
    assert noisy_op.real_matrix is not real
Пример #11
0
def test_equal_method_of_representations():
    q = cirq.LineQubit(0)
    ideal = cirq.Circuit(cirq.H(q))
    noisy_xop_a = NoisyOperation(
        ideal=cirq.Circuit(cirq.X(q)), real=np.zeros(shape=(4, 4)),
    )
    noisy_zop_a = NoisyOperation(
        ideal=cirq.Circuit(cirq.Z(q)), real=np.zeros(shape=(4, 4)),
    )
    rep_a = OperationRepresentation(
        ideal=ideal, basis_expansion={noisy_xop_a: 0.5, noisy_zop_a: 0.5},
    )
    noisy_xop_b = NoisyOperation(
        ideal=cirq.Circuit(cirq.X(q)), real=np.ones(shape=(4, 4)),
    )
    noisy_zop_b = NoisyOperation(
        ideal=cirq.Circuit(cirq.Z(q)), real=np.ones(shape=(4, 4)),
    )
    rep_b = OperationRepresentation(
        ideal=ideal, basis_expansion={noisy_xop_b: 0.5, noisy_zop_b: 0.5},
    )
    # Equal representation up to real superoperators
    assert rep_a == rep_b
    # Different ideal
    ideal_b = cirq.Circuit(cirq.X(q))
    rep_b = OperationRepresentation(
        ideal=ideal_b, basis_expansion={noisy_xop_b: 0.5, noisy_zop_b: 0.5},
    )
    assert rep_a != rep_b
    # Different type
    q_b = qiskit.QuantumRegister(1)
    ideal_b = qiskit.QuantumCircuit(q_b)
    ideal_b.x(q_b)
    rep_b = OperationRepresentation(
        ideal=ideal_b, basis_expansion={noisy_xop_b: 0.5, noisy_zop_b: 0.5},
    )
    assert rep_a != rep_b
    # Different length
    rep_b = OperationRepresentation(
        ideal=ideal, basis_expansion={noisy_xop_b: 0.5},
    )
    assert rep_a != rep_b
    # Different operations
    noisy_diff = NoisyOperation(ideal=cirq.Circuit(cirq.H(q)))
    rep_b = OperationRepresentation(
        ideal=ideal, basis_expansion={noisy_xop_b: 0.5, noisy_diff: 0.5},
    )
    assert rep_a != rep_b
    # Different coefficients
    rep_b = OperationRepresentation(
        ideal=ideal, basis_expansion={noisy_xop_b: 0.7, noisy_zop_b: 0.5},
    )
    assert rep_a != rep_b
Пример #12
0
def test_with_qubits():
    real = np.zeros(shape=(16, 16))
    qreg = [cirq.NamedQubit("Dummy 1"), cirq.NamedQubit("Dummy 2")]
    ideal = cirq.Circuit(cirq.ops.H.on(qreg[0]), cirq.ops.CNOT.on(*qreg))
    noisy_op = NoisyOperation(ideal, real)

    assert set(noisy_op.qubits) == set(qreg)
    assert np.allclose(noisy_op.real_matrix, real)

    qubits = cirq.LineQubit.range(2)
    new_noisy_op = noisy_op.with_qubits(qubits)
    assert set(new_noisy_op.qubits) == set(qubits)
    assert np.allclose(new_noisy_op.real_matrix, real)
Пример #13
0
def test_add_simple():
    ideal = cirq.Circuit([cirq.X.on(cirq.NamedQubit("Q"))])
    real = np.random.rand(4, 4)

    noisy_op1 = NoisyOperation(ideal, real)
    noisy_op2 = NoisyOperation(ideal, real)

    noisy_op = noisy_op1 + noisy_op2

    correct = cirq.Circuit([cirq.X.on(cirq.NamedQubit("Q"))] * 2)

    assert _equal(noisy_op._ideal, correct, require_qubit_equality=True)
    assert np.allclose(noisy_op.real_matrix, real @ real)
Пример #14
0
def test_get_sequences_simple(length):
    rng = np.random.RandomState(seed=1)
    noisy_basis = NoisyBasis(
        NoisyOperation.from_cirq(ideal=cirq.I, real=rng.rand(4, 4)),
        NoisyOperation.from_cirq(ideal=cirq.X, real=rng.rand(4, 4)),
    )

    sequences = noisy_basis.get_sequences(length=length)
    assert all(isinstance(s, NoisyOperation) for s in sequences)
    assert len(sequences) == len(noisy_basis) ** length

    for sequence in sequences:
        assert len(sequence.ideal_circuit()) == length
Пример #15
0
def test_transform_qubits_multiple_qubits(qubits, real):
    qreg = [cirq.NamedQubit("Dummy 1"), cirq.NamedQubit("Dummy 2")]
    ideal = cirq.Circuit(cirq.ops.H.on(qreg[0]), cirq.ops.CNOT.on(*qreg))
    noisy_op = NoisyOperation(ideal, real)

    assert set(noisy_op.qubits) != set(qubits)
    if real is not None:
        assert np.allclose(noisy_op.real_matrix, real)

    noisy_op.transform_qubits(qubits)
    assert set(noisy_op.qubits) == set(qubits)
    if real is not None:
        assert np.allclose(noisy_op.real_matrix, real)
Пример #16
0
def test_noisy_basis_add():
    rng = np.random.RandomState(seed=1)
    noisy_basis = NoisyBasis(
        NoisyOperation.from_cirq(ideal=cirq.I, real=rng.rand(4, 4)),
        NoisyOperation.from_cirq(ideal=cirq.X, real=rng.rand(4, 4)),
    )
    assert len(noisy_basis) == 2

    noisy_basis.add(
        NoisyOperation.from_cirq(ideal=cirq.Y, real=rng.rand(4, 4)),
        NoisyOperation.from_cirq(ideal=cirq.Z, real=rng.rand(4, 4)),
    )
    assert len(noisy_basis) == 4
Пример #17
0
def test_pyquil_noisy_basis():
    rng = np.random.RandomState(seed=1)

    noisy_basis = NoisyBasis(
        NoisyOperation(ideal=pyquil.Program(pyquil.gates.I(0)),
                       real=rng.rand(4, 4)),
        NoisyOperation(ideal=pyquil.Program(pyquil.gates.Y(0)),
                       real=rng.rand(4, 4)),
    )
    assert len(noisy_basis) == 2

    for op in noisy_basis.elements:
        assert isinstance(op.ideal_circuit(), pyquil.Program)
        assert isinstance(op._ideal, cirq.Circuit)
Пример #18
0
def test_noisy_basis_simple():
    rng = np.random.RandomState(seed=1)
    noisy_basis = NoisyBasis(
        NoisyOperation.from_cirq(circuit=cirq.I, channel_matrix=rng.rand(4,
                                                                         4)),
        NoisyOperation.from_cirq(circuit=cirq.X, channel_matrix=rng.rand(4,
                                                                         4)),
        NoisyOperation.from_cirq(circuit=cirq.Y, channel_matrix=rng.rand(4,
                                                                         4)),
        NoisyOperation.from_cirq(circuit=cirq.Z, channel_matrix=rng.rand(4,
                                                                         4)),
    )
    assert len(noisy_basis) == 4
    assert noisy_basis.all_qubits() == {cirq.LineQubit(0)}
Пример #19
0
def test_add_pyquil_noisy_operations():
    ideal = pyquil.Program(pyquil.gates.X(0))
    real = np.random.rand(4, 4)

    noisy_op1 = NoisyOperation(ideal, real)
    noisy_op2 = NoisyOperation(ideal, real)

    noisy_op = noisy_op1 + noisy_op2

    correct = cirq.Circuit([cirq.X.on(cirq.NamedQubit("Q"))] * 2)

    assert _equal(noisy_op._ideal, correct, require_qubit_equality=False)
    assert np.allclose(noisy_op.ideal_unitary, np.identity(2))
    assert np.allclose(noisy_op.real_matrix, real @ real)
Пример #20
0
def test_representation_coeff_of_nonexistant_operation():
    qbit = cirq.LineQubit(0)
    ideal = cirq.Circuit(cirq.X(qbit))

    noisy_xop = NoisyOperation.from_cirq(circuit=cirq.X,
                                         channel_matrix=np.zeros(shape=(4, 4)))

    decomp = OperationRepresentation(ideal=ideal,
                                     basis_expansion=dict([(noisy_xop, 0.5)]))

    noisy_zop = NoisyOperation.from_cirq(circuit=cirq.Z,
                                         channel_matrix=np.zeros(shape=(4, 4)))
    with pytest.raises(ValueError, match="does not appear in the basis"):
        decomp.coeff_of(noisy_zop)
Пример #21
0
def get_test_representation():
    ideal = cirq.Circuit(cirq.H(cirq.LineQubit(0)))

    noisy_xop = NoisyOperation.from_cirq(
        ideal=cirq.X, real=np.zeros(shape=(4, 4))
    )
    noisy_zop = NoisyOperation.from_cirq(
        ideal=cirq.Z, real=np.zeros(shape=(4, 4))
    )

    decomp = OperationRepresentation(
        ideal=ideal, basis_expansion={noisy_xop: 0.5, noisy_zop: -0.5}
    )
    return ideal, noisy_xop, noisy_zop, decomp
Пример #22
0
def test_print_cirq_operation_representation():
    ideal = cirq.Circuit(cirq.H(cirq.LineQubit(0)))

    noisy_xop = NoisyOperation.from_cirq(
        ideal=cirq.X, real=np.zeros(shape=(4, 4))
    )
    noisy_zop = NoisyOperation.from_cirq(
        ideal=cirq.Z, real=np.zeros(shape=(4, 4))
    )

    decomp = OperationRepresentation(
        ideal=ideal, basis_expansion={noisy_xop: 0.5, noisy_zop: 0.5, },
    )

    expected = r"0: ───H─── = 0.500*0: ───X───+0.500*0: ───Z───"
    assert str(decomp) == expected
Пример #23
0
def test_transform_qubits_single_qubit(qubit, real):
    gate = cirq.H
    noisy_op = NoisyOperation.from_cirq(gate, real)

    assert set(noisy_op.qubits) != {qubit}
    noisy_op.transform_qubits(qubit)
    assert set(noisy_op.qubits) == {qubit}
Пример #24
0
def test_find_optimal_representation_no_superoperator_error():
    q = LineQubit(0)
    # Define noisy operation without superoperator matrix
    noisy_op = NoisyOperation(Circuit(X(q)))
    noisy_basis = NoisyBasis(noisy_op)
    with raises(ValueError, match="numerical superoperator matrix"):
        find_optimal_representation(Circuit(X(q)), noisy_basis)
Пример #25
0
def _represent_operation_with_amplitude_damping_noise(
    ideal_operation: Circuit,
    noise_level: float,
) -> OperationRepresentation:
    r"""Returns the quasi-probability representation of the input
    single-qubit ``ideal_operation`` with respect to a basis of noisy
    operations.

    Any ideal single-qubit unitary followed by local amplitude-damping noise
    of equal ``noise_level`` is assumed to be in the basis of implementable
    operations.

    The representation is based on the analytical result presented
    in :cite:`Takagi2020`.

    Args:
        ideal_operation: The ideal operation (as a QPROGRAM) to represent.
        noise_level: The noise level of each amplitude damping channel.

    Returns:
        The quasi-probability representation of the ``ideal_operation``.

    .. note::
        The input ``ideal_operation`` is typically a QPROGRAM with a single
        gate but could also correspond to a sequence of more gates.
        This is possible as long as the unitary associated to the input
        QPROGRAM, followed by a single final amplitude damping channel, is
        physically implementable.

    .. note::
        The input ``ideal_operation`` must be a ``cirq.Circuit``.
    """

    if not isinstance(ideal_operation, Circuit):
        raise NotImplementedError(
            "The input ideal_operation must be a cirq.Circuit.", )

    qubits = ideal_operation.all_qubits()

    if len(qubits) == 1:
        q = tuple(qubits)[0]

        eta_0 = (1 + np.sqrt(1 - noise_level)) / (2 * (1 - noise_level))
        eta_1 = (1 - np.sqrt(1 - noise_level)) / (2 * (1 - noise_level))
        eta_2 = -noise_level / (1 - noise_level)
        etas = [eta_0, eta_1, eta_2]
        post_ops = [[], Z(q), reset(q)]

    else:
        raise ValueError(  # pragma: no cover
            "Only single-qubit operations are supported."  # pragma: no cover
        )  # pragma: no cover

    # Basis of implementable operations as circuits
    imp_op_circuits = [ideal_operation + Circuit(op) for op in post_ops]

    # Build basis_expantion
    expansion = {NoisyOperation(c): a for c, a in zip(imp_op_circuits, etas)}

    return OperationRepresentation(ideal_operation, expansion)
Пример #26
0
def test_add_qiskit_noisy_operations():
    qreg = qiskit.QuantumRegister(1)
    ideal = qiskit.QuantumCircuit(qreg)
    _ = ideal.x(qreg)
    real = np.random.rand(4, 4)

    noisy_op1 = NoisyOperation(ideal, real)
    noisy_op2 = NoisyOperation(ideal, real)

    noisy_op = noisy_op1 + noisy_op2

    correct = cirq.Circuit([cirq.X.on(cirq.NamedQubit("Q"))] * 2)

    assert _equal(noisy_op._ideal, correct, require_qubit_equality=False)
    assert np.allclose(noisy_op.ideal_unitary, np.identity(2))
    assert np.allclose(noisy_op.real_matrix, real @ real)
Пример #27
0
def test_add_bad_type():
    ideal = cirq.Circuit([cirq.X.on(cirq.NamedQubit("Q"))])
    real = np.random.rand(4, 4)

    noisy_op = NoisyOperation(ideal, real)

    with pytest.raises(ValueError, match="must be a NoisyOperation"):
        noisy_op + ideal
Пример #28
0
def test_noisy_basis_add():
    rng = np.random.RandomState(seed=1)
    noisy_basis = NoisyBasis(
        NoisyOperation.from_cirq(circuit=cirq.I, channel_matrix=rng.rand(4,
                                                                         4)),
        NoisyOperation.from_cirq(circuit=cirq.X, channel_matrix=rng.rand(4,
                                                                         4)),
    )
    assert len(noisy_basis) == 2

    noisy_basis.add(
        NoisyOperation.from_cirq(circuit=cirq.Y, channel_matrix=rng.rand(4,
                                                                         4)),
        NoisyOperation.from_cirq(circuit=cirq.Z, channel_matrix=rng.rand(4,
                                                                         4)),
    )
    assert len(noisy_basis) == 4
Пример #29
0
def test_on_each_multiple_qubits(qubits, real):
    noisy_ops = NoisyOperation.on_each(cirq.CNOT, qubits=qubits, real=real)
    assert len(noisy_ops) == 2

    for i, op in enumerate(noisy_ops):
        if real is not None:
            assert np.allclose(op.real_matrix, real)
        assert op.num_qubits == 2
        assert set(op.qubits) == set(qubits[i])
Пример #30
0
def test_qiskit_noisy_basis():
    rng = np.random.RandomState(seed=1)

    qreg = qiskit.QuantumRegister(1)
    xcirc = qiskit.QuantumCircuit(qreg)
    _ = xcirc.x(qreg)
    zcirc = qiskit.QuantumCircuit(qreg)
    _ = zcirc.z(qreg)

    noisy_basis = NoisyBasis(
        NoisyOperation(ideal=xcirc, real=rng.rand(4, 4)),
        NoisyOperation(ideal=zcirc, real=rng.rand(4, 4)),
    )
    assert len(noisy_basis) == 2

    for op in noisy_basis.elements:
        assert isinstance(op.ideal_circuit(), qiskit.QuantumCircuit)
        assert isinstance(op._ideal, cirq.Circuit)