def test_initial_guess_in_minimize_one_norm(): for noise_level in [0.7, 0.9]: depo_kraus = global_depolarizing_kraus(noise_level, num_qubits=1) depo_super = kraus_to_super(depo_kraus) ideal_matrix = kraus_to_super(kraus(H)) basis_matrices = [ depo_super @ kraus_to_super(kraus(gate)) @ ideal_matrix for gate in [I, X, Y, Z, H] ] optimal_coeffs = minimize_one_norm( ideal_matrix, basis_matrices, initial_guess=[1.0, 1.0, 1.0, 1.0, 1.0], ) represented_mat = sum( [eta * mat for eta, mat in zip(optimal_coeffs, basis_matrices)] ) assert np.allclose(ideal_matrix, represented_mat) # Test bad argument with raises(ValueError, match="shapes"): minimize_one_norm( ideal_matrix, basis_matrices, initial_guess=[1], )
def test_channel(): class NoDetailsGate(cirq.Gate): def num_qubits(self) -> int: return 1 assert not cirq.has_kraus(NoDetailsGate().with_probability(0.5)) assert cirq.kraus(NoDetailsGate().with_probability(0.5), None) is None assert cirq.kraus(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.kraus(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.kraus(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.kraus(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, )
def test_measurement_channel(): np.testing.assert_allclose( cirq.kraus(cirq.MeasurementGate(1, 'a')), (np.array([[1, 0], [0, 0]]), np.array([[0, 0], [0, 1]])), ) cirq.testing.assert_consistent_channel(cirq.MeasurementGate(1, 'a')) assert not cirq.has_mixture(cirq.MeasurementGate(1, 'a')) # yapf: disable np.testing.assert_allclose( cirq.kraus(cirq.MeasurementGate(2, 'a')), (np.array([[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]), np.array([[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]), np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0]]), np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1]]))) np.testing.assert_allclose( cirq.kraus(cirq.MeasurementGate(2, 'a', qid_shape=(2, 3))), (np.diag([1, 0, 0, 0, 0, 0]), np.diag([0, 1, 0, 0, 0, 0]), np.diag([0, 0, 1, 0, 0, 0]), np.diag([0, 0, 0, 1, 0, 0]), np.diag([0, 0, 0, 0, 1, 0]), np.diag([0, 0, 0, 0, 0, 1])))
def test_noisy_moment_two_qubit(): q0, q1 = cirq.LineQubit.range(2) model = ThermalNoiseModel( qubits={q0, q1}, gate_durations_ns={cirq.PhasedXZGate: 25.0, cirq.CZPowGate: 25.0}, heat_rate_GHz={q0: 1e-5, q1: 2e-5}, cool_rate_GHz={q0: 1e-4, q1: 2e-4}, dephase_rate_GHz={q0: 3e-4, q1: 4e-4}, require_physical_tag=False, ) gate = cirq.CZ**0.5 moment = cirq.Moment(gate.on(q0, q1)) noisy_moment = model.noisy_moment(moment, system_qubits=[q0, q1]) assert noisy_moment[0] == moment assert len(noisy_moment[1]) == 2 noisy_choi_0 = cirq.kraus_to_choi(cirq.kraus(noisy_moment[1].operations[0])) assert np.allclose( noisy_choi_0, [ [9.99750343e-01, 0, 0, 9.91164267e-01], [0, 2.49656565e-03, 0, 0], [0, 0, 2.49656565e-04, 0], [9.91164267e-01, 0, 0, 9.97503434e-01], ], ) noisy_choi_1 = cirq.kraus_to_choi(cirq.kraus(noisy_moment[1].operations[1])) assert np.allclose( noisy_choi_1, [ [9.99501372e-01, 0, 0, 9.87330937e-01], [0, 4.98627517e-03, 0, 0], [0, 0, 4.98627517e-04, 0], [9.87330937e-01, 0, 0, 9.95013725e-01], ], )
def test_two_qubit_gates(op): q0, q1 = cirq.LineQubit.range(2) props = TestNoiseProperties( **default_props([q0, q1], [(q0, q1), (q1, q0)])) model = NoiseModelFromNoiseProperties(props) circuit = cirq.Circuit(op) noisy_circuit = circuit.with_noise(model) assert len(noisy_circuit.moments) == 3 assert len(noisy_circuit.moments[0].operations) == 1 assert noisy_circuit.moments[0].operations[0] == op.with_tags( PHYSICAL_GATE_TAG) # Depolarizing noise assert len(noisy_circuit.moments[1].operations) == 1 depol_op = noisy_circuit.moments[1].operations[0] assert isinstance(depol_op.gate, cirq.DepolarizingChannel) assert np.isclose(depol_op.gate.p, 0.00952008) # Thermal noise assert len(noisy_circuit.moments[2].operations) == 2 thermal_op_0 = noisy_circuit.moments[2].operation_at(q0) thermal_op_1 = noisy_circuit.moments[2].operation_at(q1) assert isinstance(thermal_op_0.gate, cirq.KrausChannel) assert isinstance(thermal_op_1.gate, cirq.KrausChannel) thermal_choi_0 = cirq.kraus_to_choi(cirq.kraus(thermal_op_0)) thermal_choi_1 = cirq.kraus_to_choi(cirq.kraus(thermal_op_1)) expected_thermal_choi = np.array([ [1, 0, 0, 9.99680051e-01], [0, 3.19948805e-04, 0, 0], [0, 0, 0, 0], [9.99680051e-01, 0, 0, 9.99680051e-01], ]) assert np.allclose(thermal_choi_0, expected_thermal_choi) assert np.allclose(thermal_choi_1, expected_thermal_choi)
def test_measurement_channel(): np.testing.assert_allclose( cirq.kraus(cirq.MeasurementGate(1)), (np.array([[1, 0], [0, 0]]), np.array([[0, 0], [0, 1]])), ) # yapf: disable np.testing.assert_allclose( cirq.kraus(cirq.MeasurementGate(2)), (np.array([[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]), np.array([[0, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]), np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 1, 0], [0, 0, 0, 0]]), np.array([[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 1]]))) np.testing.assert_allclose( cirq.kraus(cirq.MeasurementGate(2, qid_shape=(2, 3))), (np.diag([1, 0, 0, 0, 0, 0]), np.diag([0, 1, 0, 0, 0, 0]), np.diag([0, 0, 1, 0, 0, 0]), np.diag([0, 0, 0, 1, 0, 0]), np.diag([0, 0, 0, 0, 1, 0]), np.diag([0, 0, 0, 0, 0, 1])))
def test_channel(): a = cirq.NamedQubit('a') op = cirq.bit_flip(0.5).on(a) np.testing.assert_allclose(cirq.kraus(op), cirq.kraus(op.gate)) assert cirq.has_kraus(op) assert cirq.kraus(cirq.SingleQubitGate()(a), None) is None assert not cirq.has_kraus(cirq.SingleQubitGate()(a))
def assert_not_implemented(val): with pytest.raises(TypeError, match='returned NotImplemented'): _ = cirq.kraus(val) assert cirq.kraus(val, None) is None assert cirq.kraus(val, NotImplemented) is NotImplemented assert cirq.kraus(val, (1, )) == (1, ) assert cirq.kraus(val, LOCAL_DEFAULT) is LOCAL_DEFAULT assert not cirq.has_kraus(val)
def test_unitary_returns_not_implemented(): class ReturnsNotImplemented: def _unitary_(self): return NotImplemented with pytest.raises(TypeError, match='returned NotImplemented'): _ = cirq.kraus(ReturnsNotImplemented()) assert cirq.kraus(ReturnsNotImplemented(), None) is None assert cirq.kraus(ReturnsNotImplemented(), NotImplemented) is NotImplemented assert cirq.kraus(ReturnsNotImplemented(), (1,)) == (1,) assert cirq.kraus(ReturnsNotImplemented(), LOCAL_DEFAULT) is LOCAL_DEFAULT
def test_two_qubit_gates(op): q0, q1 = cirq.LineQubit.range(2) props = sample_noise_properties([q0, q1], [(q0, q1), (q1, q0)]) model = NoiseModelFromGoogleNoiseProperties(props) circuit = cirq.Circuit(op) noisy_circuit = circuit.with_noise(model) assert len(noisy_circuit.moments) == 4 assert len(noisy_circuit.moments[0].operations) == 1 assert noisy_circuit.moments[0].operations[0] == op.with_tags( PHYSICAL_GATE_TAG) # Depolarizing noise assert len(noisy_circuit.moments[1].operations) == 1 depol_op = noisy_circuit.moments[1].operations[0] assert isinstance(depol_op.gate, cirq.DepolarizingChannel) assert np.isclose(depol_op.gate.p, 0.00719705) # FSim angle corrections assert len(noisy_circuit.moments[2].operations) == 1 fsim_op = noisy_circuit.moments[2].operations[0] assert isinstance(fsim_op.gate, cirq.PhasedFSimGate) assert fsim_op == PhasedFSimGate(theta=0.01, zeta=0.03, chi=0.04, gamma=0.05, phi=0.02).on(q0, q1) # Thermal noise assert len(noisy_circuit.moments[3].operations) == 2 thermal_op_0 = noisy_circuit.moments[3].operation_at(q0) thermal_op_1 = noisy_circuit.moments[3].operation_at(q1) assert isinstance(thermal_op_0.gate, cirq.KrausChannel) assert isinstance(thermal_op_1.gate, cirq.KrausChannel) thermal_choi_0 = cirq.kraus_to_choi(cirq.kraus(thermal_op_0)) thermal_choi_1 = cirq.kraus_to_choi(cirq.kraus(thermal_op_1)) expected_thermal_choi = np.array([ [1, 0, 0, 9.99680051e-01], [0, 3.19948805e-04, 0, 0], [0, 0, 0, 0], [9.99680051e-01, 0, 0, 9.99680051e-01], ]) assert np.allclose(thermal_choi_0, expected_thermal_choi) assert np.allclose(thermal_choi_1, expected_thermal_choi) # Pauli error for depol_op + fsim_op + thermal_op_(0|1) == total (0.01) depol_pauli_err = 1 - cirq.qis.measures.entanglement_fidelity(depol_op) fsim_pauli_err = 1 - cirq.qis.measures.entanglement_fidelity(fsim_op) thermal0_pauli_err = 1 - cirq.qis.measures.entanglement_fidelity( thermal_op_0) thermal1_pauli_err = 1 - cirq.qis.measures.entanglement_fidelity( thermal_op_1) total_err = depol_pauli_err + thermal0_pauli_err + thermal1_pauli_err + fsim_pauli_err assert np.isclose(total_err, TWO_QUBIT_ERROR)
def test_super_to_choi(): for noise_level in [0, 0.3, 1]: super_damping = kraus_to_super(amplitude_damping_kraus(noise_level, 1)) # Apply Pauli Y to get some complex numbers super_op = np.kron(kraus(Y)[0], kraus(Y)[0].conj()) @ super_damping choi_state = super_to_choi(super_op) # expected result q = LineQubit(0) choi_expected = _operation_to_choi( [AmplitudeDampingChannel(noise_level)(q), Y(q)]) assert np.allclose(choi_state, choi_expected)
def test_channel_no_methods(): class NoMethod: pass with pytest.raises(TypeError, match='no _kraus_ or _mixture_ or _unitary_ method'): _ = cirq.kraus(NoMethod()) assert cirq.kraus(NoMethod(), None) is None assert cirq.kraus(NoMethod, NotImplemented) is NotImplemented assert cirq.kraus(NoMethod(), (1,)) == (1,) assert cirq.kraus(NoMethod(), LOCAL_DEFAULT) is LOCAL_DEFAULT assert not cirq.has_kraus(NoMethod())
def test_state_prep_channel_kraus_small(): gate = cirq.StatePreparationChannel(np.array([0.0, 1.0]))(cirq.LineQubit(0)) np.testing.assert_almost_equal(cirq.kraus(gate), (np.array( [[0.0, 0.0], [1.0, 0.0]]), np.array([[0.0, 0.0], [0.0, 1.0]]))) assert cirq.has_kraus(gate) assert not cirq.has_mixture(gate) gate = cirq.StatePreparationChannel(np.array([1.0, 0.0]))(cirq.LineQubit(0)) np.testing.assert_almost_equal(cirq.kraus(gate), (np.array( [[1.0, 0.0], [0.0, 0.0]]), np.array([[0.0, 1.0], [0.0, 0.0]]))) assert cirq.has_kraus(gate) assert not cirq.has_mixture(gate)
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.kraus(ReturnsUnitary()), (u,)) np.testing.assert_equal(cirq.kraus(ReturnsUnitary(), None), (u,)) np.testing.assert_equal(cirq.kraus(ReturnsUnitary(), NotImplemented), (u,)) np.testing.assert_equal(cirq.kraus(ReturnsUnitary(), (1,)), (u,)) np.testing.assert_equal(cirq.kraus(ReturnsUnitary(), LOCAL_DEFAULT), (u,)) assert cirq.has_kraus(ReturnsUnitary())
def test_kraus(): I = np.eye(2) X = np.array([[0, 1], [1, 0]]) Y = np.array([[0, -1j], [1j, 0]]) Z = np.diag([1, -1]) a, b = cirq.LineQubit.range(2) m = cirq.Moment() assert cirq.has_kraus(m) k = cirq.kraus(m) assert len(k) == 1 assert np.allclose(k[0], np.array([[1.0]])) m = cirq.Moment(cirq.S(a)) assert cirq.has_kraus(m) k = cirq.kraus(m) assert len(k) == 1 assert np.allclose(k[0], np.diag([1, 1j])) m = cirq.Moment(cirq.CNOT(a, b)) assert cirq.has_kraus(m) k = cirq.kraus(m) print(k[0]) assert len(k) == 1 assert np.allclose( k[0], np.array([[1, 0, 0, 0], [0, 1, 0, 0], [0, 0, 0, 1], [0, 0, 1, 0]])) p = 0.1 m = cirq.Moment(cirq.depolarize(p).on(a)) assert cirq.has_kraus(m) k = cirq.kraus(m) assert len(k) == 4 assert np.allclose(k[0], np.sqrt(1 - p) * I) assert np.allclose(k[1], np.sqrt(p / 3) * X) assert np.allclose(k[2], np.sqrt(p / 3) * Y) assert np.allclose(k[3], np.sqrt(p / 3) * Z) p = 0.2 q = 0.3 m = cirq.Moment(cirq.bit_flip(p).on(a), cirq.phase_flip(q).on(b)) assert cirq.has_kraus(m) k = cirq.kraus(m) assert len(k) == 4 assert np.allclose(k[0], np.sqrt((1 - p) * (1 - q)) * np.kron(I, I)) assert np.allclose(k[1], np.sqrt(q * (1 - p)) * np.kron(I, Z)) assert np.allclose(k[2], np.sqrt(p * (1 - q)) * np.kron(X, I)) assert np.allclose(k[3], np.sqrt(p * q) * np.kron(X, Z))
def test_noisy_moment_one_qubit(): q0, q1 = cirq.LineQubit.range(2) model = ThermalNoiseModel( qubits={q0, q1}, gate_durations_ns={cirq.PhasedXZGate: 25.0, cirq.CZPowGate: 25.0}, heat_rate_GHz={q0: 1e-5, q1: 2e-5}, cool_rate_GHz={q0: 1e-4, q1: 2e-4}, dephase_rate_GHz={q0: 3e-4, q1: 4e-4}, require_physical_tag=False, ) gate = cirq.PhasedXZGate(x_exponent=1, z_exponent=0.5, axis_phase_exponent=0.25) moment = cirq.Moment(gate.on(q0)) noisy_moment = model.noisy_moment(moment, system_qubits=[q0, q1]) assert noisy_moment[0] == moment # Noise applies to both qubits, even if only one is acted upon. assert len(noisy_moment[1]) == 2 noisy_choi = cirq.kraus_to_choi(cirq.kraus(noisy_moment[1].operations[0])) assert np.allclose( noisy_choi, [ [9.99750343e-01, 0, 0, 9.91164267e-01], [0, 2.49656565e-03, 0, 0], [0, 0, 2.49656565e-04, 0], [9.91164267e-01, 0, 0, 9.97503434e-01], ], )
def test_wait_gates(): q0 = cirq.LineQubit(0) props = sample_noise_properties([q0], []) model = NoiseModelFromGoogleNoiseProperties(props) op = cirq.wait(q0, nanos=100) circuit = cirq.Circuit(op) noisy_circuit = circuit.with_noise(model) assert len(noisy_circuit.moments) == 2 assert noisy_circuit.moments[0].operations[0] == op.with_tags(PHYSICAL_GATE_TAG) # No depolarizing noise because WaitGate has none. assert len(noisy_circuit.moments[1].operations) == 1 thermal_op = noisy_circuit.moments[1].operations[0] assert isinstance(thermal_op.gate, cirq.KrausChannel) thermal_choi = cirq.kraus_to_choi(cirq.kraus(thermal_op)) assert np.allclose( thermal_choi, [ [1, 0, 0, 9.990005e-01], [0, 9.99500167e-04, 0, 0], [0, 0, 0, 0], [9.990005e-01, 0, 0, 9.990005e-01], ], )
def test_asymmetric_depolarizing_channel(): d = cirq.asymmetric_depolarize(0.1, 0.2, 0.3) np.testing.assert_almost_equal( cirq.kraus(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_kraus(d)
def test_from_matrix_close_kraus(unitary: np.ndarray): gate = cirq.PhasedXZGate.from_matrix(unitary) kraus = cirq.kraus(gate) assert len(kraus) == 1 cirq.testing.assert_allclose_up_to_global_phase(kraus[0], unitary, atol=1e-8)
def test_noise_from_wait(): # Verify that wait-gate noise is duration-dependent. q0 = cirq.LineQubit(0) gate_durations = {cirq.ZPowGate: 25.0} heat_rate_GHz = {q0: 1e-5} cool_rate_GHz = {q0: 1e-4} model = ThermalNoiseModel( qubits={q0}, gate_durations_ns=gate_durations, heat_rate_GHz=heat_rate_GHz, cool_rate_GHz=cool_rate_GHz, dephase_rate_GHz=None, require_physical_tag=False, skip_measurements=True, ) moment = cirq.Moment(cirq.wait(q0, nanos=100)) noisy_moment = model.noisy_moment(moment, system_qubits=[q0]) assert noisy_moment[0] == moment assert len(noisy_moment[1]) == 1 noisy_choi = cirq.kraus_to_choi(cirq.kraus(noisy_moment[1].operations[0])) print(noisy_choi) assert np.allclose( noisy_choi, [ [9.99005480e-01, 0, 0, 9.94515097e-01], [0, 9.94520111e-03, 0, 0], [0, 0, 9.94520111e-04, 0], [9.94515097e-01, 0, 0, 9.90054799e-01], ], )
def test_single_qubit_gates(op): q0 = cirq.LineQubit(0) props = TestNoiseProperties(**default_props([q0], [])) model = NoiseModelFromNoiseProperties(props) circuit = cirq.Circuit(op) noisy_circuit = circuit.with_noise(model) assert len(noisy_circuit.moments) == 3 assert len(noisy_circuit.moments[0].operations) == 1 assert noisy_circuit.moments[0].operations[0] == op.with_tags( PHYSICAL_GATE_TAG) # Depolarizing noise assert len(noisy_circuit.moments[1].operations) == 1 depol_op = noisy_circuit.moments[1].operations[0] assert isinstance(depol_op.gate, cirq.DepolarizingChannel) assert np.isclose(depol_op.gate.p, 0.00081252) # Thermal noise assert len(noisy_circuit.moments[2].operations) == 1 thermal_op = noisy_circuit.moments[2].operations[0] assert isinstance(thermal_op.gate, cirq.KrausChannel) thermal_choi = cirq.kraus_to_choi(cirq.kraus(thermal_op)) assert np.allclose( thermal_choi, [ [1, 0, 0, 9.99750031e-01], [0, 2.49968753e-04, 0, 0], [0, 0, 0, 0], [9.99750031e-01, 0, 0, 9.99750031e-01], ], )
def test_kraus_too_big(): m = cirq.Moment(cirq.IdentityGate(11).on(*cirq.LineQubit.range(11))) assert not cirq.has_kraus(m) assert not m._has_superoperator_() assert m._kraus_() is NotImplemented assert m._superoperator_() is NotImplemented assert cirq.kraus(m, default=None) is None
def test_depolarizing_channel_two_qubits(): d = cirq.depolarize(0.15, n_qubits=2) np.testing.assert_almost_equal( cirq.kraus(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_kraus(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 compute_channel_matrix(channel: cirq.SupportsChannel) -> np.ndarray: ks = cirq.kraus(channel) d_out, d_in = ks[0].shape m = np.zeros((d_out * d_out, d_in * d_in), dtype=np.complex128) for k, e_in in enumerate(generate_standard_operator_basis(d_in, d_in)): m[:, k] = np.reshape(apply_channel(channel, e_in), d_out * d_out) return m
def test_explicit_kraus(): a0 = np.array([[0, 0], [1, 0]]) a1 = np.array([[1, 0], [0, 0]]) c = (a0, a1) class ReturnsKraus: def _kraus_(self) -> Sequence[np.ndarray]: return c assert cirq.kraus(ReturnsKraus()) is c assert cirq.kraus(ReturnsKraus(), None) is c assert cirq.kraus(ReturnsKraus(), NotImplemented) is c assert cirq.kraus(ReturnsKraus(), (1, )) is c assert cirq.kraus(ReturnsKraus(), LOCAL_DEFAULT) is c assert cirq.has_kraus(ReturnsKraus())
def compute_choi(channel: cirq.SupportsChannel) -> np.ndarray: ks = cirq.kraus(channel) d_out, d_in = ks[0].shape d = d_in * d_out c = np.zeros((d, d), dtype=np.complex128) for e in generate_standard_operator_basis(d_in, d_in): c += np.kron(apply_channel(channel, e), e) return c
def apply_channel(channel: cirq.SupportsChannel, rho: np.ndarray) -> np.ndarray: ks = cirq.kraus(channel) d_out, d_in = ks[0].shape assert rho.shape == (d_in, d_in) out = np.zeros((d_out, d_out), dtype=np.complex128) for k in ks: out += k @ rho @ k.conj().T return out
def assert_channel_sums_to_identity(val): m = cirq.kraus(val) s = sum(np.conj(e.T) @ e for e in m) np.testing.assert_allclose(s, np.eye( np.prod(cirq.qid_shape(val), dtype=np.int64)), atol=1e-8)
def find_optimal_representation( ideal_operation: QPROGRAM, noisy_basis: NoisyBasis, tol: float = 1.0e-8, initial_guess: Optional[np.ndarray] = None, ) -> OperationRepresentation: r"""Returns the ``OperationRepresentaiton`` of the input ideal operation which minimizes the one-norm of the associated quasi-probability distribution. More precicely, it solve the following optimization problem: .. math:: \min_{{\eta_\alpha}} = \sum_\alpha |\eta_\alpha|, \text{ such that } \mathcal G = \sum_\alpha \eta_\alpha \mathcal O_\alpha, where :math:`\{\mathcal O_j\}` is the input basis of noisy operations. Args: ideal_operation: The ideal operation to represent. noisy_basis: The ``NoisyBasis`` in which the ``ideal_operation`` should be represented. It must contain ``NoisyOperation`` objects which are initialized with a numerical superoperator matrix. tol: The error tolerance for each matrix element of the represented operation. initial_guess: Optional initial guess for the coefficients :math:`\{ \eta_\alpha \}``. Returns: The optimal OperationRepresentation. """ ideal_cirq_circuit, _ = convert_to_mitiq(ideal_operation) ideal_matrix = kraus_to_super( cast(List[np.ndarray], kraus(ideal_cirq_circuit))) basis_set = noisy_basis.elements try: basis_matrices = [noisy_op.channel_matrix for noisy_op in basis_set] except ValueError as err: if str(err) == "The channel matrix is unknown.": raise ValueError( "The input noisy_basis should contain NoisyOperation objects" " which are initialized with a numerical superoperator matrix." ) else: raise err # pragma no cover # Run numerical optimization problem quasi_prob_dist = minimize_one_norm( ideal_matrix, basis_matrices, tol=tol, initial_guess=initial_guess, ) basis_expansion = {op: eta for op, eta in zip(basis_set, quasi_prob_dist)} return OperationRepresentation(ideal_operation, basis_expansion)
def test_depolarizing_channel(): d = cirq.depolarize(0.3) np.testing.assert_almost_equal( cirq.kraus(d), (np.sqrt(0.7) * np.eye(2), np.sqrt(0.1) * X, np.sqrt(0.1) * Y, np.sqrt(0.1) * Z), ) cirq.testing.assert_consistent_channel(d) cirq.testing.assert_consistent_mixture(d)