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))
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)
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)
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)
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, )
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)
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)
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
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())
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)
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))
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())
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())
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)
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)
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)
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
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)
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))
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)
def test_has_channel(cls): assert cirq.has_channel(cls())
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)
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, )