Beispiel #1
0
def test_channel():
    a = cirq.NamedQubit('a')
    op = cirq.bit_flip(0.5).on(a)
    np.testing.assert_allclose(cirq.channel(op), cirq.channel(op.gate))
    assert cirq.has_channel(op)

    assert cirq.channel(cirq.SingleQubitGate()(a), None) is None
    assert not cirq.has_channel(cirq.SingleQubitGate()(a))
Beispiel #2
0
def test_parameterized():
    op = cirq.X.with_probability(sympy.Symbol('x'))
    assert cirq.is_parameterized(op)
    assert not cirq.has_channel(op)
    assert not cirq.has_mixture(op)

    op2 = cirq.resolve_parameters(op, {'x': 0.5})
    assert op2 == cirq.X.with_probability(0.5)
    assert not cirq.is_parameterized(op2)
    assert cirq.has_channel(op2)
    assert cirq.has_mixture(op2)
Beispiel #3
0
def test_asymmetric_depolarizing_channel():
    d = cirq.asymmetric_depolarize(0.1, 0.2, 0.3)
    np.testing.assert_almost_equal(
        cirq.channel(d),
        (np.sqrt(0.4) * np.eye(2), np.sqrt(0.1) * X, np.sqrt(0.2) * Y, np.sqrt(0.3) * Z),
    )
    assert cirq.has_channel(d)
Beispiel #4
0
def test_depolarizing_channel_two_qubits():
    d = cirq.depolarize(0.15, n_qubits=2)
    np.testing.assert_almost_equal(
        cirq.channel(d),
        (
            np.sqrt(0.85) * np.eye(4),
            np.sqrt(0.01) * np.kron(np.eye(2), X),
            np.sqrt(0.01) * np.kron(np.eye(2), Y),
            np.sqrt(0.01) * np.kron(np.eye(2), Z),
            np.sqrt(0.01) * np.kron(X, np.eye(2)),
            np.sqrt(0.01) * np.kron(X, X),
            np.sqrt(0.01) * np.kron(X, Y),
            np.sqrt(0.01) * np.kron(X, Z),
            np.sqrt(0.01) * np.kron(Y, np.eye(2)),
            np.sqrt(0.01) * np.kron(Y, X),
            np.sqrt(0.01) * np.kron(Y, Y),
            np.sqrt(0.01) * np.kron(Y, Z),
            np.sqrt(0.01) * np.kron(Z, np.eye(2)),
            np.sqrt(0.01) * np.kron(Z, X),
            np.sqrt(0.01) * np.kron(Z, Y),
            np.sqrt(0.01) * np.kron(Z, Z),
        ),
    )
    assert cirq.has_channel(d)

    assert d.num_qubits() == 2
    cirq.testing.assert_has_diagram(
        cirq.Circuit(d(*cirq.LineQubit.range(2))),
        """
0: ───D(0.15)───
      │
1: ───#2────────
        """,
    )
def test_phase_damping_channel():
    d = cirq.phase_damp(0.3)
    np.testing.assert_almost_equal(
        cirq.channel(d), (np.array([[1.0, 0.], [0., np.sqrt(1 - 0.3)]]),
                          np.array([[0., 0.], [0., np.sqrt(0.3)]])))
    assert cirq.has_channel(d)
    assert not cirq.has_mixture(d)
def test_depolarizing_channel():
    d = cirq.depolarize(0.3)
    np.testing.assert_almost_equal(cirq.channel(d),
                                   (np.sqrt(0.7) * np.eye(2),
                                    np.sqrt(0.1) * X,
                                    np.sqrt(0.1) * Y,
                                    np.sqrt(0.1) * Z))
    assert cirq.has_channel(d)
def test_generalized_amplitude_damping_channel():
    d = cirq.generalized_amplitude_damp(0.1, 0.3)
    np.testing.assert_almost_equal(cirq.channel(d),
              (np.sqrt(0.1) * np.array([[1., 0.], [0., np.sqrt(1.-0.3)]]),
               np.sqrt(0.1) * np.array([[0., np.sqrt(0.3)], [0., 0.]]),
               np.sqrt(0.9) * np.array([[np.sqrt(1. - 0.3), 0.], [0., 1.]]),
               np.sqrt(0.9) * np.array([[0., 0.], [np.sqrt(0.3), 0.]])))
    assert cirq.has_channel(d)
    assert not cirq.has_mixture_channel(d)
Beispiel #8
0
def test_has_channel():
    class HasChannel:
        def _has_channel_(self) -> bool:
            return True

    assert cirq.has_channel(HasChannel())

    class HasMixture:
        def _has_mixture_(self) -> bool:
            return True

    assert cirq.has_channel(HasMixture())

    class HasUnitary:
        def _has_unitary_(self) -> bool:
            return True

    assert cirq.has_channel(HasUnitary())
def test_reset_channel():
    r = cirq.reset(cirq.LineQubit(0))
    np.testing.assert_almost_equal(
        cirq.channel(r),
        (np.array([[1., 0.], [0., 0]]), np.array([[0., 1.], [0., 0.]])))
    assert cirq.has_channel(r)
    assert not cirq.has_mixture(r)
    assert cirq.qid_shape(r) == (2, )

    r = cirq.reset(cirq.LineQid(0, dimension=3))
    np.testing.assert_almost_equal(
        cirq.channel(r),
        (np.array([[1, 0, 0], [0, 0, 0], [0, 0, 0]]),
         np.array([[0, 1, 0], [0, 0, 0], [0, 0, 0]]),
         np.array([[0, 0, 1], [0, 0, 0], [0, 0, 0]])))  # yapf: disable
    assert cirq.has_channel(r)
    assert not cirq.has_mixture(r)
    assert cirq.qid_shape(r) == (3, )
Beispiel #10
0
def assert_not_implemented(val):
    with pytest.raises(TypeError, match='returned NotImplemented'):
        _ = cirq.channel(val)

    assert cirq.channel(val, None) is None
    assert cirq.channel(val, NotImplemented) is NotImplemented
    assert cirq.channel(val, (1, )) == (1, )
    assert cirq.channel(val, LOCAL_DEFAULT) is LOCAL_DEFAULT

    assert not cirq.has_channel(val)
Beispiel #11
0
def test_amplitude_damping_channel():
    d = cirq.amplitude_damp(0.3)
    np.testing.assert_almost_equal(
        cirq.channel(d),
        (
            np.array([[1.0, 0.0], [0.0, np.sqrt(1.0 - 0.3)]]),
            np.array([[0.0, np.sqrt(0.3)], [0.0, 0.0]]),
        ),
    )
    assert cirq.has_channel(d)
    assert not cirq.has_mixture(d)
Beispiel #12
0
def test_multi_asymmetric_depolarizing_channel():
    d = cirq.asymmetric_depolarize(error_probabilities={'II': 0.8, 'XX': 0.2})
    np.testing.assert_almost_equal(
        cirq.channel(d),
        (np.sqrt(0.8) * np.eye(4), np.sqrt(0.2) * np.kron(X, X)))
    assert cirq.has_channel(d)
    np.testing.assert_equal(d._num_qubits_(), 2)
    with pytest.raises(ValueError, match="num_qubits should be 1"):
        assert d.p_x == 0.0
    with pytest.raises(ValueError, match="num_qubits should be 1"):
        assert d.p_y == 0.0
    with pytest.raises(ValueError, match="num_qubits should be 1"):
        assert d.p_z == 0.0
Beispiel #13
0
def test_channel_no_methods():
    class NoMethod:
        pass

    with pytest.raises(TypeError,
                       match='no _channel_ or _mixture_ or _unitary_ method'):
        _ = cirq.channel(NoMethod())

    assert cirq.channel(NoMethod(), None) is None
    assert cirq.channel(NoMethod, NotImplemented) is NotImplemented
    assert cirq.channel(NoMethod(), (1, )) == (1, )
    assert cirq.channel(NoMethod(), LOCAL_DEFAULT) is LOCAL_DEFAULT

    assert not cirq.has_channel(NoMethod())
Beispiel #14
0
def test_channel_propagates_to_gate():
    class TestGate(cirq.SingleQubitGate):
        def _channel_(self) -> np.ndarray:
            return (np.eye(2), )

        def _has_channel_(self) -> bool:
            return True

    def assert_kraus_eq(ks1: Tuple[np.ndarray, ...], ks2: Tuple[np.ndarray,
                                                                ...]) -> None:
        assert len(ks1) == len(ks2)
        for k1, k2 in zip(ks1, ks2):
            assert np.all(k1 == k2)

    identity_kraus = (np.eye(2), )
    q = cirq.LineQubit(0)
    gate = TestGate()
    gate_op = TestGate().on(q)
    with cirq.testing.assert_deprecated(deadline='v0.13', count=None):
        assert cirq.has_channel(gate)
        assert cirq.has_channel(gate_op)
        assert_kraus_eq(cirq.channel(gate), identity_kraus)
        assert_kraus_eq(cirq.channel(gate_op), identity_kraus)
Beispiel #15
0
def test_channel_generates_deprecation_warning():
    class UsesDeprecatedChannelMethod:
        def _has_channel_(self):
            return True

        def _channel_(self):
            return (np.eye(2), )

    val = UsesDeprecatedChannelMethod()
    with pytest.warns(DeprecationWarning, match='_has_kraus_'):
        assert cirq.has_channel(val)
    with pytest.warns(DeprecationWarning, match='_kraus_'):
        ks = cirq.channel(val)
        assert len(ks) == 1
        assert np.all(ks[0] == np.eye(2))
Beispiel #16
0
def test_channel_fallback_to_unitary():
    u = np.array([[1, 0], [1, 0]])

    class ReturnsUnitary:
        def _unitary_(self) -> np.ndarray:
            return u

    np.testing.assert_equal(cirq.channel(ReturnsUnitary()), (u, ))
    np.testing.assert_equal(cirq.channel(ReturnsUnitary(), None), (u, ))
    np.testing.assert_equal(cirq.channel(ReturnsUnitary(), NotImplemented),
                            (u, ))
    np.testing.assert_equal(cirq.channel(ReturnsUnitary(), (1, )), (u, ))
    np.testing.assert_equal(cirq.channel(ReturnsUnitary(), LOCAL_DEFAULT),
                            (u, ))

    assert cirq.has_channel(ReturnsUnitary())
Beispiel #17
0
def test_channel():
    a0 = np.array([[0, 0], [1, 0]])
    a1 = np.array([[1, 0], [0, 0]])
    c = (a0, a1)

    class ReturnsChannel:
        def _channel_(self) -> Sequence[np.ndarray]:
            return c

    assert cirq.channel(ReturnsChannel()) is c
    assert cirq.channel(ReturnsChannel(), None) is c
    assert cirq.channel(ReturnsChannel(), NotImplemented) is c
    assert cirq.channel(ReturnsChannel(), (1, )) is c
    assert cirq.channel(ReturnsChannel(), LOCAL_DEFAULT) is c

    assert cirq.has_channel(ReturnsChannel())
Beispiel #18
0
def test_channel_fallback_to_mixture():
    m = ((0.3, cirq.unitary(cirq.X)), (0.4, cirq.unitary(cirq.Y)),
         (0.3, cirq.unitary(cirq.Z)))

    class ReturnsMixture:
        def _mixture_(self) -> Iterable[Tuple[float, np.ndarray]]:
            return m

    c = (np.sqrt(0.3) * cirq.unitary(cirq.X),
         np.sqrt(0.4) * cirq.unitary(cirq.Y),
         np.sqrt(0.3) * cirq.unitary(cirq.Z))

    np.allclose(cirq.channel(ReturnsMixture()), c)
    np.allclose(cirq.channel(ReturnsMixture(), None), c)
    np.allclose(cirq.channel(ReturnsMixture(), NotImplemented), c)
    np.allclose(cirq.channel(ReturnsMixture(), (1, )), c)
    np.allclose(cirq.channel(ReturnsMixture(), LOCAL_DEFAULT), c)

    assert cirq.has_channel(ReturnsMixture())
def test_depolarizing_channel_two_qubits():
    d = cirq.depolarize(0.15, n_qubits=2)
    np.testing.assert_almost_equal(cirq.channel(d), (
        np.sqrt(0.85) * np.eye(4),
        np.sqrt(0.01) * np.kron(np.eye(2), X),
        np.sqrt(0.01) * np.kron(np.eye(2), Y),
        np.sqrt(0.01) * np.kron(np.eye(2), Z),
        np.sqrt(0.01) * np.kron(X, np.eye(2)),
        np.sqrt(0.01) * np.kron(X, X),
        np.sqrt(0.01) * np.kron(X, Y),
        np.sqrt(0.01) * np.kron(X, Z),
        np.sqrt(0.01) * np.kron(Y, np.eye(2)),
        np.sqrt(0.01) * np.kron(Y, X),
        np.sqrt(0.01) * np.kron(Y, Y),
        np.sqrt(0.01) * np.kron(Y, Z),
        np.sqrt(0.01) * np.kron(Z, np.eye(2)),
        np.sqrt(0.01) * np.kron(Z, X),
        np.sqrt(0.01) * np.kron(Z, Y),
        np.sqrt(0.01) * np.kron(Z, Z),
    ))
    assert cirq.has_channel(d)
Beispiel #20
0
def test_reset_channel():
    np.testing.assert_almost_equal(
        cirq.channel(cirq.RESET),
        (np.array([[1., 0.], [0., 0]]), np.array([[0., 1.], [0., 0.]])))
    assert cirq.has_channel(cirq.RESET)
    assert not cirq.has_mixture_channel(cirq.RESET)
Beispiel #21
0
def test_tagged_operation_forwards_protocols():
    """The results of all protocols applied to an operation with a tag should
    be equivalent to the result without tags.
    """
    q1 = cirq.GridQubit(1, 1)
    q2 = cirq.GridQubit(1, 2)
    h = cirq.H(q1)
    tag = 'tag1'
    tagged_h = cirq.H(q1).with_tags(tag)

    np.testing.assert_equal(cirq.unitary(tagged_h), cirq.unitary(h))
    assert cirq.has_unitary(tagged_h)
    assert cirq.decompose(tagged_h) == cirq.decompose(h)
    assert cirq.pauli_expansion(tagged_h) == cirq.pauli_expansion(h)
    assert cirq.equal_up_to_global_phase(h, tagged_h)
    assert np.isclose(cirq.channel(h), cirq.channel(tagged_h)).all()

    assert cirq.measurement_key(cirq.measure(q1, key='blah').with_tags(tag)) == 'blah'

    parameterized_op = cirq.XPowGate(exponent=sympy.Symbol('t'))(q1).with_tags(tag)
    assert cirq.is_parameterized(parameterized_op)
    resolver = cirq.study.ParamResolver({'t': 0.25})
    assert cirq.resolve_parameters(parameterized_op, resolver) == cirq.XPowGate(exponent=0.25)(
        q1
    ).with_tags(tag)
    assert cirq.resolve_parameters_once(parameterized_op, resolver) == cirq.XPowGate(exponent=0.25)(
        q1
    ).with_tags(tag)

    y = cirq.Y(q1)
    tagged_y = cirq.Y(q1).with_tags(tag)
    assert tagged_y ** 0.5 == cirq.YPowGate(exponent=0.5)(q1)
    assert tagged_y * 2 == (y * 2)
    assert 3 * tagged_y == (3 * y)
    assert cirq.phase_by(y, 0.125, 0) == cirq.phase_by(tagged_y, 0.125, 0)
    controlled_y = tagged_y.controlled_by(q2)
    assert controlled_y.qubits == (
        q2,
        q1,
    )
    assert isinstance(controlled_y, cirq.Operation)
    assert not isinstance(controlled_y, cirq.TaggedOperation)

    clifford_x = cirq.SingleQubitCliffordGate.X(q1)
    tagged_x = cirq.SingleQubitCliffordGate.X(q1).with_tags(tag)
    assert cirq.commutes(clifford_x, clifford_x)
    assert cirq.commutes(tagged_x, clifford_x)
    assert cirq.commutes(clifford_x, tagged_x)
    assert cirq.commutes(tagged_x, tagged_x)

    assert cirq.trace_distance_bound(y ** 0.001) == cirq.trace_distance_bound(
        (y ** 0.001).with_tags(tag)
    )

    flip = cirq.bit_flip(0.5)(q1)
    tagged_flip = cirq.bit_flip(0.5)(q1).with_tags(tag)
    assert cirq.has_mixture(tagged_flip)
    assert cirq.has_channel(tagged_flip)

    flip_mixture = cirq.mixture(flip)
    tagged_mixture = cirq.mixture(tagged_flip)
    assert len(tagged_mixture) == 2
    assert len(tagged_mixture[0]) == 2
    assert len(tagged_mixture[1]) == 2
    assert tagged_mixture[0][0] == flip_mixture[0][0]
    assert np.isclose(tagged_mixture[0][1], flip_mixture[0][1]).all()
    assert tagged_mixture[1][0] == flip_mixture[1][0]
    assert np.isclose(tagged_mixture[1][1], flip_mixture[1][1]).all()

    qubit_map = {q1: 'q1'}
    qasm_args = cirq.QasmArgs(qubit_id_map=qubit_map)
    assert cirq.qasm(h, args=qasm_args) == cirq.qasm(tagged_h, args=qasm_args)

    cirq.testing.assert_has_consistent_apply_unitary(tagged_h)
Beispiel #22
0
    def translate_cirq_to_qtrajectory(
        self,
        qubit_order: cirq.ops.QubitOrderOrList = cirq.ops.QubitOrder.DEFAULT
    ) -> qsim.NoisyCircuit:
        """
        Translates this noisy Cirq circuit to the qsim representation.
        :qubit_order: Ordering of qubits
        :return: a C++ qsim NoisyCircuit object
        """
        qsim_ncircuit = qsim.NoisyCircuit()
        ordered_qubits = cirq.ops.QubitOrder.as_qubit_order(
            qubit_order).order_for(self.all_qubits())

        # qsim numbers qubits in reverse order from cirq
        ordered_qubits = list(reversed(ordered_qubits))

        qsim_ncircuit.num_qubits = len(ordered_qubits)

        def has_qsim_kind(op: cirq.ops.GateOperation):
            return _cirq_gate_kind(op.gate) != None

        def to_matrix(op: cirq.ops.GateOperation):
            mat = cirq.unitary(op.gate, None)
            if mat is None:
                return NotImplemented

            return cirq.ops.MatrixGate(mat).on(*op.qubits)

        qubit_to_index_dict = {q: i for i, q in enumerate(ordered_qubits)}
        time_offset = 0
        for moment in self:
            moment_length = 0
            ops_by_gate = []
            ops_by_mix = []
            ops_by_channel = []
            # Capture ops of each type in the appropriate list.
            for qsim_op in moment:
                if cirq.has_unitary(qsim_op) or cirq.is_measurement(qsim_op):
                    oplist = cirq.decompose(qsim_op,
                                            fallback_decomposer=to_matrix,
                                            keep=has_qsim_kind)
                    ops_by_gate.append(oplist)
                    moment_length = max(moment_length, len(oplist))
                    pass
                elif cirq.has_mixture(qsim_op):
                    ops_by_mix.append(qsim_op)
                    moment_length = max(moment_length, 1)
                    pass
                elif cirq.has_channel(qsim_op):
                    ops_by_channel.append(qsim_op)
                    moment_length = max(moment_length, 1)
                    pass
                else:
                    raise ValueError(f'Encountered unparseable op: {qsim_op}')

            # Gates must be added in time order.
            for gi in range(moment_length):
                # Handle gate output.
                for gate_ops in ops_by_gate:
                    if gi >= len(gate_ops):
                        continue
                    qsim_op = gate_ops[gi]
                    time = time_offset + gi
                    gate_kind = _cirq_gate_kind(qsim_op.gate)
                    add_op_to_circuit(qsim_op, time, qubit_to_index_dict,
                                      qsim_ncircuit)
                # Handle mixture output.
                for mixture in ops_by_mix:
                    mixdata = []
                    for prob, mat in cirq.mixture(mixture):
                        square_mat = np.reshape(mat,
                                                (int(np.sqrt(mat.size)), -1))
                        unitary = cirq.is_unitary(square_mat)
                        # Package matrix into a qsim-friendly format.
                        mat = np.reshape(mat, (-1, )).astype(np.complex64,
                                                             copy=False)
                        mixdata.append((prob, mat.view(np.float32), unitary))
                    qubits = [qubit_to_index_dict[q] for q in mixture.qubits]
                    qsim.add_channel(time_offset, qubits, mixdata,
                                     qsim_ncircuit)
                # Handle channel output.
                for channel in ops_by_channel:
                    chdata = []
                    for i, mat in enumerate(cirq.channel(channel)):
                        square_mat = np.reshape(mat,
                                                (int(np.sqrt(mat.size)), -1))
                        unitary = cirq.is_unitary(square_mat)
                        singular_vals = np.linalg.svd(square_mat)[1]
                        lower_bound_prob = min(singular_vals)**2
                        # Package matrix into a qsim-friendly format.
                        mat = np.reshape(mat, (-1, )).astype(np.complex64,
                                                             copy=False)
                        chdata.append(
                            (lower_bound_prob, mat.view(np.float32), unitary))
                    qubits = [qubit_to_index_dict[q] for q in channel.qubits]
                    qsim.add_channel(time_offset, qubits, chdata,
                                     qsim_ncircuit)
            time_offset += moment_length

        return qsim_ncircuit
Beispiel #23
0
def test_bit_flip_channel():
    d = cirq.bit_flip(0.3)
    np.testing.assert_almost_equal(
        cirq.channel(d), (np.sqrt(1.0 - 0.3) * np.eye(2), np.sqrt(0.3) * X))
    assert cirq.has_channel(d)
Beispiel #24
0
def test_has_channel_protocol_is_deprecated():
    with cirq.testing.assert_deprecated(deadline='v0.13'):
        assert cirq.has_channel(cirq.depolarize(0.1)) == cirq.has_kraus(cirq.depolarize(0.1))
Beispiel #25
0
def test_has_channel_when_decomposed(decomposed_cls):
    op = HasChannelWhenDecomposed(decomposed_cls).on(cirq.NamedQubit('test'))
    assert cirq.has_channel(op)
    assert not cirq.has_channel(op, allow_decompose=False)
Beispiel #26
0
def test_has_channel(cls):
    assert cirq.has_channel(cls())
Beispiel #27
0
def circuit_to_density_matrix_tensors(
    circuit: cirq.Circuit,
    qubits: Optional[Sequence[cirq.LineQubit]] = None
) -> Tuple[List[qtn.Tensor], Dict['cirq.Qid', int], Dict[Tuple[str, str],
                                                         Tuple[float, float]]]:
    """Given a circuit with mixtures or channels, construct a tensor network
    representation of the density matrix.

    This assumes you start in the |0..0><0..0| state. Indices are named
    "nf{i}_q{x}" and "nb{i}_q{x}" where i is a time index and x is a
    qubit index. nf- and nb- refer to the "forwards" and "backwards"
    copies of the circuit. Kraus indices are named "k{j}" where j is an
    independent "kraus" internal index which you probably never need to access.

    Args:
        circuit: The circuit containing operations that support the
            cirq.unitary() or cirq.channel() protocols.
        qubits: The qubits in the circuit.

    Returns:
        tensors: A list of Quimb Tensor objects
        qubit_frontier: A mapping from qubit to time index at the end of
            the circuit. This can be used to deduce the names of the free
            tensor indices.
        positions: A positions dictionary suitable for passing to tn.graph()'s
            `fix` argument to draw the resulting tensor network similar to a
            quantum circuit.
    """
    if qubits is None:
        # coverage: ignore
        qubits = sorted(cast(Iterable[cirq.LineQubit], circuit.all_qubits()))

    qubit_frontier: Dict[cirq.Qid, int] = {q: 0 for q in qubits}
    kraus_frontier = 0
    positions: Dict[Tuple[str, str], Tuple[float, float]] = {}
    tensors: List[qtn.Tensor] = []

    x_scale = 2
    y_scale = 3
    x_nudge = 0.3
    n_qubits = len(qubits)
    yb_offset = (n_qubits + 0.5) * y_scale

    def _positions(mi, qubits):
        return _add_to_positions(
            positions,
            mi,
            qubits,
            tot_n_qubits=n_qubits,
            x_scale=x_scale,
            y_scale=y_scale,
            x_nudge=x_nudge,
            yb_offset=yb_offset,
        )

    # Initialize forwards and backwards qubits into the 0 state, i.e. prepare
    # rho_0 = |0><0|.
    for q in qubits:
        tensors += [
            qtn.Tensor(data=quimb.up().squeeze(),
                       inds=(f'nf0_q{q.x}', ),
                       tags={'Q0', 'i0f', _qpos_tag(q)}),
            qtn.Tensor(data=quimb.up().squeeze(),
                       inds=(f'nb0_q{q.x}', ),
                       tags={'Q0', 'i0b', _qpos_tag(q)}),
        ]
        _positions(0, q)

    for mi, moment in enumerate(circuit.moments):
        for op in moment.operations:
            start_inds_f = [f'nf{qubit_frontier[q]}_q{q.x}' for q in op.qubits]
            start_inds_b = [f'nb{qubit_frontier[q]}_q{q.x}' for q in op.qubits]
            for q in op.qubits:
                qubit_frontier[q] += 1
            end_inds_f = [f'nf{qubit_frontier[q]}_q{q.x}' for q in op.qubits]
            end_inds_b = [f'nb{qubit_frontier[q]}_q{q.x}' for q in op.qubits]

            if cirq.has_unitary(op):
                U = cirq.unitary(op).reshape(
                    (2, ) * 2 * len(op.qubits)).astype(np.complex128)
                tensors.append(
                    qtn.Tensor(
                        data=U,
                        inds=end_inds_f + start_inds_f,
                        tags={
                            f'Q{len(op.qubits)}', f'i{mi + 1}f',
                            _qpos_tag(op.qubits)
                        },
                    ))
                tensors.append(
                    qtn.Tensor(
                        data=np.conj(U),
                        inds=end_inds_b + start_inds_b,
                        tags={
                            f'Q{len(op.qubits)}', f'i{mi + 1}b',
                            _qpos_tag(op.qubits)
                        },
                    ))
            elif cirq.has_channel(op):
                K = np.asarray(cirq.channel(op), dtype=np.complex128)
                kraus_inds = [f'k{kraus_frontier}']
                tensors.append(
                    qtn.Tensor(
                        data=K,
                        inds=kraus_inds + end_inds_f + start_inds_f,
                        tags={
                            f'kQ{len(op.qubits)}', f'i{mi + 1}f',
                            _qpos_tag(op.qubits)
                        },
                    ))
                tensors.append(
                    qtn.Tensor(
                        data=np.conj(K),
                        inds=kraus_inds + end_inds_b + start_inds_b,
                        tags={
                            f'kQ{len(op.qubits)}', f'i{mi + 1}b',
                            _qpos_tag(op.qubits)
                        },
                    ))
                kraus_frontier += 1
            else:
                raise ValueError(repr(op))  # coverage: ignore

            _positions(mi + 1, op.qubits)
    return tensors, qubit_frontier, positions
def test_phase_flip_channel():
    d = cirq.phase_flip(0.3)
    np.testing.assert_almost_equal(
        cirq.channel(d), (np.sqrt(1. - 0.3) * np.eye(2), np.sqrt(0.3) * Z))
    assert cirq.has_channel(d)
Beispiel #29
0
def test_channel():

    class NoDetailsGate(cirq.Gate):

        def num_qubits(self) -> int:
            return 1

    assert not cirq.has_channel(NoDetailsGate().with_probability(0.5))
    assert cirq.channel(NoDetailsGate().with_probability(0.5), None) is None
    assert cirq.channel(cirq.X.with_probability(sympy.Symbol('x')),
                        None) is None
    assert_channel_sums_to_identity(cirq.X.with_probability(0.25))
    assert_channel_sums_to_identity(cirq.bit_flip(0.75).with_probability(0.25))
    assert_channel_sums_to_identity(
        cirq.amplitude_damp(0.75).with_probability(0.25))

    m = cirq.channel(cirq.X.with_probability(0.25))
    assert len(m) == 2
    np.testing.assert_allclose(
        m[0],
        cirq.unitary(cirq.X) * np.sqrt(0.25),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        m[1],
        cirq.unitary(cirq.I) * np.sqrt(0.75),
        atol=1e-8,
    )

    m = cirq.channel(cirq.bit_flip(0.75).with_probability(0.25))
    assert len(m) == 3
    np.testing.assert_allclose(
        m[0],
        cirq.unitary(cirq.I) * np.sqrt(0.25) * np.sqrt(0.25),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        m[1],
        cirq.unitary(cirq.X) * np.sqrt(0.25) * np.sqrt(0.75),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        m[2],
        cirq.unitary(cirq.I) * np.sqrt(0.75),
        atol=1e-8,
    )

    m = cirq.channel(cirq.amplitude_damp(0.75).with_probability(0.25))
    assert len(m) == 3
    np.testing.assert_allclose(
        m[0],
        np.array([[1, 0], [0, np.sqrt(1 - 0.75)]]) * np.sqrt(0.25),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        m[1],
        np.array([[0, np.sqrt(0.75)], [0, 0]]) * np.sqrt(0.25),
        atol=1e-8,
    )
    np.testing.assert_allclose(
        m[2],
        cirq.unitary(cirq.I) * np.sqrt(0.75),
        atol=1e-8,
    )