From 04f6ce046ea962561b90bc7858b9e624f7f3e36a Mon Sep 17 00:00:00 2001 From: Orion Martin <40585662+95-martin-orion@users.noreply.github.com> Date: Tue, 3 May 2022 15:48:39 -0700 Subject: [PATCH] Put noise before gates. --- .../cirq/contrib/noise_models/noise_models.py | 6 +-- .../contrib/noise_models/noise_models_test.py | 40 +++++++------- .../cirq/devices/insertion_noise_model.py | 3 +- .../devices/insertion_noise_model_test.py | 20 +++---- cirq-core/cirq/devices/noise_model.py | 2 +- cirq-core/cirq/devices/noise_model_test.py | 6 +-- ...superconducting_qubits_noise_properties.py | 4 +- ...conducting_qubits_noise_properties_test.py | 54 ++++++++++--------- cirq-core/cirq/devices/thermal_noise_model.py | 2 +- .../cirq/devices/thermal_noise_model_test.py | 20 +++---- .../experimental/noise_models/noise_models.py | 6 +-- .../noise_models/noise_models_test.py | 12 ++--- 12 files changed, 88 insertions(+), 87 deletions(-) diff --git a/cirq-core/cirq/contrib/noise_models/noise_models.py b/cirq-core/cirq/contrib/noise_models/noise_models.py index c7a6f0afb05..668af61afc7 100644 --- a/cirq-core/cirq/contrib/noise_models/noise_models.py +++ b/cirq-core/cirq/contrib/noise_models/noise_models.py @@ -44,10 +44,10 @@ def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid' return moment return [ - moment, circuits.Moment( self.qubit_noise_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits ), + moment, ] @@ -141,7 +141,7 @@ def __init__(self, depol_prob: float, bitflip_prob: float): def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): if validate_all_measurements(moment): return [circuits.Moment(self.readout_noise_gate(q) for q in system_qubits), moment] - return [moment, circuits.Moment(self.qubit_noise_gate(q) for q in system_qubits)] + return [circuits.Moment(self.qubit_noise_gate(q) for q in system_qubits), moment] class DepolarizingWithDampedReadoutNoiseModel(devices.NoiseModel): @@ -176,4 +176,4 @@ def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid' moment, ] else: - return [moment, circuits.Moment(self.qubit_noise_gate(q) for q in system_qubits)] + return [circuits.Moment(self.qubit_noise_gate(q) for q in system_qubits), moment] diff --git a/cirq-core/cirq/contrib/noise_models/noise_models_test.py b/cirq-core/cirq/contrib/noise_models/noise_models_test.py index df9e6fbf724..0aaf3cee7fd 100644 --- a/cirq-core/cirq/contrib/noise_models/noise_models_test.py +++ b/cirq-core/cirq/contrib/noise_models/noise_models_test.py @@ -22,15 +22,15 @@ def test_depol_noise(): noise_model = ccn.DepolarizingNoiseModel(depol_prob=0.005) qubits = cirq.LineQubit.range(2) moment = cirq.Moment([cirq.X(qubits[0]), cirq.Y(qubits[1])]) - noisy_mom = noise_model.noisy_moment(moment, system_qubits=qubits) - assert len(noisy_mom) == 2 - assert noisy_mom[0] == moment - for g in noisy_mom[1]: + noisy_moment = noise_model.noisy_moment(moment, system_qubits=qubits) + assert len(noisy_moment) == 2 + assert noisy_moment[1] == moment + for g in noisy_moment[0]: assert isinstance(g.gate, cirq.DepolarizingChannel) # Composes depolarization noise with readout noise. -def test_readout_noise_after_moment(): +def test_readout_noise_before_moment(): program = cirq.Circuit() qubits = cirq.LineQubit.range(3) program.append( @@ -53,21 +53,21 @@ def test_readout_noise_after_moment(): # Insert channels explicitly true_noisy_program = cirq.Circuit() - true_noisy_program.append([cirq.H(qubits[0])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q).with_tags(ops.VirtualTag()) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) - true_noisy_program.append([cirq.CNOT(qubits[0], qubits[1])]) + true_noisy_program.append([cirq.H(qubits[0])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q).with_tags(ops.VirtualTag()) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) - true_noisy_program.append([cirq.CNOT(qubits[1], qubits[2])]) + true_noisy_program.append([cirq.CNOT(qubits[0], qubits[1])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q).with_tags(ops.VirtualTag()) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) + true_noisy_program.append([cirq.CNOT(qubits[1], qubits[2])]) true_noisy_program.append( [cirq.BitFlipChannel(0.05).on(q).with_tags(ops.VirtualTag()) for q in qubits] ) @@ -82,7 +82,7 @@ def test_readout_noise_after_moment(): # Composes depolarization, damping, and readout noise (in that order). -def test_decay_noise_after_moment(): +def test_decay_noise_before_moment(): program = cirq.Circuit() qubits = cirq.LineQubit.range(3) program.append( @@ -107,21 +107,21 @@ def test_decay_noise_after_moment(): # Insert channels explicitly true_noisy_program = cirq.Circuit() - true_noisy_program.append([cirq.H(qubits[0])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q).with_tags(ops.VirtualTag()) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) - true_noisy_program.append([cirq.CNOT(qubits[0], qubits[1])]) + true_noisy_program.append([cirq.H(qubits[0])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q).with_tags(ops.VirtualTag()) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) - true_noisy_program.append([cirq.CNOT(qubits[1], qubits[2])]) + true_noisy_program.append([cirq.CNOT(qubits[0], qubits[1])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q).with_tags(ops.VirtualTag()) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) + true_noisy_program.append([cirq.CNOT(qubits[1], qubits[2])]) true_noisy_program.append( [cirq.AmplitudeDampingChannel(0.02).on(q).with_tags(ops.VirtualTag()) for q in qubits] ) @@ -139,7 +139,7 @@ def test_decay_noise_after_moment(): # Test the aggregate noise models. -def test_aggregate_readout_noise_after_moment(): +def test_aggregate_readout_noise_before_moment(): program = cirq.Circuit() qubits = cirq.LineQubit.range(3) program.append( @@ -160,21 +160,21 @@ def test_aggregate_readout_noise_after_moment(): # Insert channels explicitly true_noisy_program = cirq.Circuit() - true_noisy_program.append([cirq.H(qubits[0])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) - true_noisy_program.append([cirq.CNOT(qubits[0], qubits[1])]) + true_noisy_program.append([cirq.H(qubits[0])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) - true_noisy_program.append([cirq.CNOT(qubits[1], qubits[2])]) + true_noisy_program.append([cirq.CNOT(qubits[0], qubits[1])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) + true_noisy_program.append([cirq.CNOT(qubits[1], qubits[2])]) true_noisy_program.append([cirq.BitFlipChannel(0.05).on(q) for q in qubits]) true_noisy_program.append( [ @@ -186,7 +186,7 @@ def test_aggregate_readout_noise_after_moment(): assert_equivalent_op_tree(true_noisy_program, noisy_circuit) -def test_aggregate_decay_noise_after_moment(): +def test_aggregate_decay_noise_before_moment(): program = cirq.Circuit() qubits = cirq.LineQubit.range(3) program.append( @@ -209,21 +209,21 @@ def test_aggregate_decay_noise_after_moment(): # Insert channels explicitly true_noisy_program = cirq.Circuit() - true_noisy_program.append([cirq.H(qubits[0])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) - true_noisy_program.append([cirq.CNOT(qubits[0], qubits[1])]) + true_noisy_program.append([cirq.H(qubits[0])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) - true_noisy_program.append([cirq.CNOT(qubits[1], qubits[2])]) + true_noisy_program.append([cirq.CNOT(qubits[0], qubits[1])]) true_noisy_program.append( [cirq.DepolarizingChannel(0.01).on(q) for q in qubits], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) + true_noisy_program.append([cirq.CNOT(qubits[1], qubits[2])]) true_noisy_program.append([cirq.AmplitudeDampingChannel(0.02).on(q) for q in qubits]) true_noisy_program.append([cirq.BitFlipChannel(0.05).on(q) for q in qubits]) true_noisy_program.append( diff --git a/cirq-core/cirq/devices/insertion_noise_model.py b/cirq-core/cirq/devices/insertion_noise_model.py index 33553216de5..80bfebd03bd 100644 --- a/cirq-core/cirq/devices/insertion_noise_model.py +++ b/cirq-core/cirq/devices/insertion_noise_model.py @@ -38,6 +38,7 @@ class InsertionNoiseModel(devices.NoiseModel): qubits and A does not) then the first one appering in this dict will match. prepend: whether to add the new moment before the current one. + Defaults to True. require_physical_tag: whether to only apply noise to operations tagged with PHYSICAL_GATE_TAG. """ @@ -45,7 +46,7 @@ class InsertionNoiseModel(devices.NoiseModel): ops_added: Dict[noise_utils.OpIdentifier, 'cirq.Operation'] = dataclasses.field( default_factory=dict ) - prepend: bool = False + prepend: bool = True require_physical_tag: bool = True def noisy_moment( diff --git a/cirq-core/cirq/devices/insertion_noise_model_test.py b/cirq-core/cirq/devices/insertion_noise_model_test.py index dc15eec2b44..74621408c23 100644 --- a/cirq-core/cirq/devices/insertion_noise_model_test.py +++ b/cirq-core/cirq/devices/insertion_noise_model_test.py @@ -24,24 +24,24 @@ def test_insertion_noise(): model = InsertionNoiseModel( {op_id0: cirq.T(q0), op_id1: cirq.H(q1)}, require_physical_tag=False ) - assert not model.prepend + assert model.prepend moment_0 = cirq.Moment(cirq.X(q0), cirq.X(q1)) assert model.noisy_moment(moment_0, system_qubits=[q0, q1]) == [ - moment_0, cirq.Moment(cirq.T(q0)), + moment_0, ] moment_1 = cirq.Moment(cirq.Z(q0), cirq.Z(q1)) assert model.noisy_moment(moment_1, system_qubits=[q0, q1]) == [ - moment_1, cirq.Moment(cirq.H(q1)), + moment_1, ] moment_2 = cirq.Moment(cirq.X(q0), cirq.Z(q1)) assert model.noisy_moment(moment_2, system_qubits=[q0, q1]) == [ - moment_2, cirq.Moment(cirq.T(q0), cirq.H(q1)), + moment_2, ] moment_3 = cirq.Moment(cirq.Z(q0), cirq.X(q1)) @@ -56,9 +56,9 @@ def test_colliding_noise_qubits(): moment_0 = cirq.Moment(cirq.CZ(q0, q1), cirq.CZ(q2, q3)) assert model.noisy_moment(moment_0, system_qubits=[q0, q1, q2, q3]) == [ - moment_0, cirq.Moment(cirq.CNOT(q1, q2)), cirq.Moment(cirq.CNOT(q1, q2)), + moment_0, ] @@ -67,13 +67,13 @@ def test_prepend(): op_id0 = OpIdentifier(cirq.XPowGate, q0) op_id1 = OpIdentifier(cirq.ZPowGate, q1) model = InsertionNoiseModel( - {op_id0: cirq.T(q0), op_id1: cirq.H(q1)}, prepend=True, require_physical_tag=False + {op_id0: cirq.T(q0), op_id1: cirq.H(q1)}, prepend=False, require_physical_tag=False ) moment_0 = cirq.Moment(cirq.X(q0), cirq.Z(q1)) assert model.noisy_moment(moment_0, system_qubits=[q0, q1]) == [ - cirq.Moment(cirq.T(q0), cirq.H(q1)), moment_0, + cirq.Moment(cirq.T(q0), cirq.H(q1)), ] @@ -86,8 +86,8 @@ def test_require_physical_tag(): moment_0 = cirq.Moment(cirq.X(q0).with_tags(PHYSICAL_GATE_TAG), cirq.Z(q1)) assert model.noisy_moment(moment_0, system_qubits=[q0, q1]) == [ - moment_0, cirq.Moment(cirq.T(q0)), + moment_0, ] @@ -102,7 +102,7 @@ def test_supertype_matching(): ) moment_0 = cirq.Moment(cirq.Rx(rads=1).on(q0)) - assert model.noisy_moment(moment_0, system_qubits=[q0]) == [moment_0, cirq.Moment(cirq.S(q0))] + assert model.noisy_moment(moment_0, system_qubits=[q0]) == [cirq.Moment(cirq.S(q0)), moment_0] moment_1 = cirq.Moment(cirq.Y(q0)) - assert model.noisy_moment(moment_1, system_qubits=[q0]) == [moment_1, cirq.Moment(cirq.T(q0))] + assert model.noisy_moment(moment_1, system_qubits=[q0]) == [cirq.Moment(cirq.T(q0)), moment_1] diff --git a/cirq-core/cirq/devices/noise_model.py b/cirq-core/cirq/devices/noise_model.py index 8300cde7003..2963a3e9a96 100644 --- a/cirq-core/cirq/devices/noise_model.py +++ b/cirq-core/cirq/devices/noise_model.py @@ -228,10 +228,10 @@ def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid' if self.is_virtual_moment(moment): return moment return [ - moment, moment_module.Moment( [self.qubit_noise_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits] ), + moment, ] def _json_dict_(self): diff --git a/cirq-core/cirq/devices/noise_model_test.py b/cirq-core/cirq/devices/noise_model_test.py index 0e66579f981..c02e15f1a3b 100644 --- a/cirq-core/cirq/devices/noise_model_test.py +++ b/cirq-core/cirq/devices/noise_model_test.py @@ -109,12 +109,12 @@ def test_constant_qubit_noise(): actual = damp_all.noisy_moments([cirq.Moment([cirq.X(a)]), cirq.Moment()], [a, b, c]) expected = [ [ - cirq.Moment([cirq.X(a)]), cirq.Moment(d.with_tags(ops.VirtualTag()) for d in [damp(a), damp(b), damp(c)]), + cirq.Moment([cirq.X(a)]), ], [ - cirq.Moment(), cirq.Moment(d.with_tags(ops.VirtualTag()) for d in [damp(a), damp(b), damp(c)]), + cirq.Moment(), ], ] assert actual == expected @@ -137,12 +137,12 @@ def test_noise_composition(): actual_sz = cirq.Circuit(noise_z.noisy_moments(circuit_s.moments, [a, b, c])) expected_circuit = cirq.Circuit( + cirq.Moment([cirq.S(a), cirq.S(b), cirq.S(c)]), cirq.Moment([cirq.X(a)]), cirq.Moment([cirq.S(a), cirq.S(b), cirq.S(c)]), cirq.Moment([cirq.Y(b)]), cirq.Moment([cirq.S(a), cirq.S(b), cirq.S(c)]), cirq.Moment([cirq.H(c)]), - cirq.Moment([cirq.S(a), cirq.S(b), cirq.S(c)]), ) # All of the gates will be the same, just out of order. Merging fixes this. diff --git a/cirq-core/cirq/devices/superconducting_qubits_noise_properties.py b/cirq-core/cirq/devices/superconducting_qubits_noise_properties.py index 64e307d4623..8b8fe11766f 100644 --- a/cirq-core/cirq/devices/superconducting_qubits_noise_properties.py +++ b/cirq-core/cirq/devices/superconducting_qubits_noise_properties.py @@ -185,8 +185,6 @@ def build_noise_models(self) -> List['cirq.NoiseModel']: noise_utils.OpIdentifier(ops.MeasurementGate, qubit) ] = ops.generalized_amplitude_damp(p, gamma).on(qubit) - noise_models.append( - devices.InsertionNoiseModel(ops_added=added_measure_errors, prepend=True) - ) + noise_models.append(devices.InsertionNoiseModel(ops_added=added_measure_errors)) return noise_models diff --git a/cirq-core/cirq/devices/superconducting_qubits_noise_properties_test.py b/cirq-core/cirq/devices/superconducting_qubits_noise_properties_test.py index 053fbb2eab9..8062c7f2862 100644 --- a/cirq-core/cirq/devices/superconducting_qubits_noise_properties_test.py +++ b/cirq-core/cirq/devices/superconducting_qubits_noise_properties_test.py @@ -218,19 +218,12 @@ def test_single_qubit_gates(op): model = NoiseModelFromNoiseProperties(props) circuit = cirq.Circuit(op) noisy_circuit = circuit.with_noise(model) + print(noisy_circuit.moments) 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 len(noisy_circuit.moments[0].operations) == 1 + thermal_op = noisy_circuit.moments[0].operations[0] assert isinstance(thermal_op.gate, cirq.KrausChannel) thermal_choi = cirq.kraus_to_choi(cirq.kraus(thermal_op)) assert np.allclose( @@ -243,6 +236,16 @@ def test_single_qubit_gates(op): ], ) + # 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) + + # Original moment + assert len(noisy_circuit.moments[2].operations) == 1 + assert noisy_circuit.moments[2].operations[0] == op.with_tags(PHYSICAL_GATE_TAG) + @pytest.mark.parametrize( 'op', [cirq.ISWAP(*cirq.LineQubit.range(2)) ** 0.6, cirq.CZ(*cirq.LineQubit.range(2)) ** 0.3] @@ -254,19 +257,11 @@ def test_two_qubit_gates(op): 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 len(noisy_circuit.moments[0].operations) == 2 + thermal_op_0 = noisy_circuit.moments[0].operation_at(q0) + thermal_op_1 = noisy_circuit.moments[0].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)) @@ -282,6 +277,16 @@ def test_two_qubit_gates(op): assert np.allclose(thermal_choi_0, expected_thermal_choi) assert np.allclose(thermal_choi_1, expected_thermal_choi) + # 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) + + # Original moment + assert len(noisy_circuit.moments[2].operations) == 1 + assert noisy_circuit.moments[2].operations[0] == op.with_tags(PHYSICAL_GATE_TAG) + def test_measure_gates(): q00, q01, q10, q11 = cirq.GridQubit.rect(2, 2) @@ -329,12 +334,10 @@ def test_wait_gates(): 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 len(noisy_circuit.moments[0].operations) == 1 + thermal_op = noisy_circuit.moments[0].operations[0] assert isinstance(thermal_op.gate, cirq.KrausChannel) thermal_choi = cirq.kraus_to_choi(cirq.kraus(thermal_op)) assert np.allclose( @@ -346,3 +349,4 @@ def test_wait_gates(): [9.990005e-01, 0, 0, 9.990005e-01], ], ) + assert noisy_circuit.moments[1].operations[0] == op.with_tags(PHYSICAL_GATE_TAG) diff --git a/cirq-core/cirq/devices/thermal_noise_model.py b/cirq-core/cirq/devices/thermal_noise_model.py index bf610973965..d2fbb7879d0 100644 --- a/cirq-core/cirq/devices/thermal_noise_model.py +++ b/cirq-core/cirq/devices/thermal_noise_model.py @@ -277,4 +277,4 @@ def noisy_moment( noise_ops.append(ops.KrausChannel(kraus_ops).on(qubit)) if not noise_ops: return [moment] - return [moment, moment_module.Moment(noise_ops)] + return [moment_module.Moment(noise_ops), moment] diff --git a/cirq-core/cirq/devices/thermal_noise_model_test.py b/cirq-core/cirq/devices/thermal_noise_model_test.py index 855cbd53e2f..00beee4ed5b 100644 --- a/cirq-core/cirq/devices/thermal_noise_model_test.py +++ b/cirq-core/cirq/devices/thermal_noise_model_test.py @@ -210,10 +210,9 @@ def test_noisy_moment_one_qubit(): 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 len(noisy_moment[0]) == 2 + noisy_choi = cirq.kraus_to_choi(cirq.kraus(noisy_moment[0].operations[0])) assert np.allclose( noisy_choi, [ @@ -223,6 +222,7 @@ def test_noisy_moment_one_qubit(): [9.91164267e-01, 0, 0, 9.97503434e-01], ], ) + assert noisy_moment[1] == moment def test_noise_from_wait(): @@ -242,9 +242,8 @@ def test_noise_from_wait(): ) 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])) + assert len(noisy_moment[0]) == 1 + noisy_choi = cirq.kraus_to_choi(cirq.kraus(noisy_moment[0].operations[0])) assert np.allclose( noisy_choi, [ @@ -254,6 +253,7 @@ def test_noise_from_wait(): [9.94515097e-01, 0, 0, 9.90054799e-01], ], ) + assert noisy_moment[1] == moment def test_symbolic_times_for_wait_gate(): @@ -288,9 +288,8 @@ def test_noisy_moment_two_qubit(): 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 len(noisy_moment[0]) == 2 + noisy_choi_0 = cirq.kraus_to_choi(cirq.kraus(noisy_moment[0].operations[0])) assert np.allclose( noisy_choi_0, [ @@ -300,7 +299,7 @@ def test_noisy_moment_two_qubit(): [9.91164267e-01, 0, 0, 9.97503434e-01], ], ) - noisy_choi_1 = cirq.kraus_to_choi(cirq.kraus(noisy_moment[1].operations[1])) + noisy_choi_1 = cirq.kraus_to_choi(cirq.kraus(noisy_moment[0].operations[1])) assert np.allclose( noisy_choi_1, [ @@ -310,3 +309,4 @@ def test_noisy_moment_two_qubit(): [9.87330937e-01, 0, 0, 9.95013725e-01], ], ) + assert noisy_moment[1] == moment diff --git a/cirq-google/cirq_google/experimental/noise_models/noise_models.py b/cirq-google/cirq_google/experimental/noise_models/noise_models.py index f5b13f4edac..d4352c5ad6c 100644 --- a/cirq-google/cirq_google/experimental/noise_models/noise_models.py +++ b/cirq-google/cirq_google/experimental/noise_models/noise_models.py @@ -80,10 +80,7 @@ def noisy_moment(self, moment: cirq.Moment, system_qubits: Sequence[cirq.Qid]) - cirq.BitFlipChannel(self.bitflip_probs[q])(q) for q in system_qubits ) ) - moments.append(moment) - return moments else: - moments.append(moment) if self.depol_probs: gated_qubits = [q for q in system_qubits if moment.operates_on_single_qubit(q)] if gated_qubits: @@ -92,7 +89,8 @@ def noisy_moment(self, moment: cirq.Moment, system_qubits: Sequence[cirq.Qid]) - cirq.DepolarizingChannel(self.depol_probs[q])(q) for q in gated_qubits ) ) - return moments + moments.append(moment) + return moments def simple_noise_from_calibration_metrics( diff --git a/cirq-google/cirq_google/experimental/noise_models/noise_models_test.py b/cirq-google/cirq_google/experimental/noise_models/noise_models_test.py index 2bf82d4a81c..ca627b5ea9f 100644 --- a/cirq-google/cirq_google/experimental/noise_models/noise_models_test.py +++ b/cirq-google/cirq_google/experimental/noise_models/noise_models_test.py @@ -141,22 +141,22 @@ def test_per_qubit_depol_noise_from_data(): # Insert channels explicitly to construct expected output. expected_program = cirq.Circuit( - cirq.Moment([cirq.H(qubits[0])]), cirq.Moment([cirq.DepolarizingChannel(DEPOL_001).on(qubits[0])]), - cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), + cirq.Moment([cirq.H(qubits[0])]), cirq.Moment( [ cirq.DepolarizingChannel(DEPOL_001).on(qubits[0]), cirq.DepolarizingChannel(DEPOL_002).on(qubits[1]), ] ), - cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), + cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment( [ cirq.DepolarizingChannel(DEPOL_001).on(qubits[0]), cirq.DepolarizingChannel(DEPOL_003).on(qubits[2]), ] ), + cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), cirq.Moment([cirq.Z(qubits[1]).with_tags(cirq.VirtualTag())]), cirq.Moment( [ @@ -285,22 +285,22 @@ def test_per_qubit_combined_noise_from_data(): # Insert channels explicitly to construct expected output. decay_prob = [1 - exp(-1 / 0.007), 1 - exp(-1 / 0.008), 1 - exp(-1 / 0.009)] expected_program = cirq.Circuit( - cirq.Moment([cirq.H(qubits[0])]), cirq.Moment([cirq.DepolarizingChannel(DEPOL_001).on(qubits[0])]), - cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), + cirq.Moment([cirq.H(qubits[0])]), cirq.Moment( [ cirq.DepolarizingChannel(DEPOL_001).on(qubits[0]), cirq.DepolarizingChannel(DEPOL_002).on(qubits[1]), ] ), - cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), + cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment( [ cirq.DepolarizingChannel(DEPOL_001).on(qubits[0]), cirq.DepolarizingChannel(DEPOL_003).on(qubits[2]), ] ), + cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), cirq.Moment([cirq.AmplitudeDampingChannel(decay_prob[i]).on(qubits[i]) for i in range(3)]), cirq.Moment( [