def test_readout_noise_after_moment(): program = cirq.Circuit() qubits = cirq.LineQubit.range(3) program.append([ cirq.H(qubits[0]), cirq.CNOT(qubits[0], qubits[1]), cirq.CNOT(qubits[1], qubits[2]) ]) program.append( [ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1'), cirq.measure(qubits[2], key='q2'), ], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) # Use noise model to generate circuit depol_noise = ccn.DepolarizingNoiseModel(depol_prob=0.01) readout_noise = ccn.ReadoutNoiseModel(bitflip_prob=0.05) noisy_circuit = cirq.Circuit(depol_noise.noisy_moments(program, qubits)) noisy_circuit = cirq.Circuit( readout_noise.noisy_moments(noisy_circuit, qubits)) # 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.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.DepolarizingChannel(0.01).on(q).with_tags(ops.VirtualTag()) for q in qubits ], strategy=cirq.InsertStrategy.NEW_THEN_INLINE, ) true_noisy_program.append([ cirq.BitFlipChannel(0.05).on(q).with_tags(ops.VirtualTag()) for q in qubits ]) true_noisy_program.append([ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1'), cirq.measure(qubits[2], key='q2'), ]) assert_equivalent_op_tree(true_noisy_program, noisy_circuit)
def test_constant_qubit_noise(): a, b, c = cirq.LineQubit.range(3) damp = cirq.amplitude_damp(0.5) damp_all = cirq.ConstantQubitNoiseModel(damp) 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.Moment( d.with_tags(ops.VirtualTag()) for d in [damp(a), damp(b), damp(c)]), ], ] assert actual == expected cirq.testing.assert_equivalent_repr(damp_all) with pytest.raises(ValueError, match='num_qubits'): _ = cirq.ConstantQubitNoiseModel(cirq.CNOT**0.01)
def test_infers_other_methods(): q = cirq.LineQubit(0) class NoiseModelWithNoisyMomentListMethod(cirq.NoiseModel): def noisy_moments(self, moments, system_qubits): result = [] for moment in moments: if moment.operations: result.append( cirq.X(moment.operations[0].qubits[0]).with_tags( ops.VirtualTag())) else: result.append([]) return result a = NoiseModelWithNoisyMomentListMethod() assert_equivalent_op_tree(a.noisy_operation(cirq.H(q)), cirq.X(q).with_tags(ops.VirtualTag())) assert_equivalent_op_tree(a.noisy_moment(cirq.Moment([cirq.H(q)]), [q]), cirq.X(q).with_tags(ops.VirtualTag())) assert_equivalent_op_tree_sequence( a.noisy_moments( [cirq.Moment(), cirq.Moment([cirq.H(q)])], [q]), [[], cirq.X(q).with_tags(ops.VirtualTag())], ) class NoiseModelWithNoisyMomentMethod(cirq.NoiseModel): def noisy_moment(self, moment, system_qubits): return [ y.with_tags(ops.VirtualTag()) for y in cirq.Y.on_each(*moment.qubits) ] b = NoiseModelWithNoisyMomentMethod() assert_equivalent_op_tree(b.noisy_operation(cirq.H(q)), cirq.Y(q).with_tags(ops.VirtualTag())) assert_equivalent_op_tree(b.noisy_moment(cirq.Moment([cirq.H(q)]), [q]), cirq.Y(q).with_tags(ops.VirtualTag())) assert_equivalent_op_tree_sequence( b.noisy_moments( [cirq.Moment(), cirq.Moment([cirq.H(q)])], [q]), [[], cirq.Y(q).with_tags(ops.VirtualTag())], ) class NoiseModelWithNoisyOperationMethod(cirq.NoiseModel): def noisy_operation(self, operation: 'cirq.Operation'): return cirq.Z(operation.qubits[0]).with_tags(ops.VirtualTag()) c = NoiseModelWithNoisyOperationMethod() assert_equivalent_op_tree(c.noisy_operation(cirq.H(q)), cirq.Z(q).with_tags(ops.VirtualTag())) assert_equivalent_op_tree(c.noisy_moment(cirq.Moment([cirq.H(q)]), [q]), cirq.Z(q).with_tags(ops.VirtualTag())) assert_equivalent_op_tree_sequence( c.noisy_moments( [cirq.Moment(), cirq.Moment([cirq.H(q)])], [q]), [[], cirq.Z(q).with_tags(ops.VirtualTag())], )
def test_per_qubit_depol_noise_from_data(): # Generate the depolarization noise model from calibration data. calibration = cirq.google.Calibration(_CALIBRATION_DATA) noise_model = simple_noise_from_calibration_metrics(calibration=calibration, depol_noise=True) # Create the circuit and apply the noise model. qubits = [cirq.GridQubit(0, 0), cirq.GridQubit(0, 1), cirq.GridQubit(1, 0)] program = cirq.Circuit( cirq.Moment([cirq.H(qubits[0])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[1])]), cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), cirq.Moment([cirq.Z(qubits[1]).with_tags(ops.VirtualTag())]), cirq.Moment( [ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1'), cirq.measure(qubits[2], key='q2'), ] ), ) noisy_circuit = cirq.Circuit(noise_model.noisy_moments(program, qubits)) # 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.DepolarizingChannel(DEPOL_001).on(qubits[0]), cirq.DepolarizingChannel(DEPOL_002).on(qubits[1]), ] ), cirq.Moment([cirq.CNOT(qubits[0], qubits[2])]), cirq.Moment( [ cirq.DepolarizingChannel(DEPOL_001).on(qubits[0]), cirq.DepolarizingChannel(DEPOL_003).on(qubits[2]), ] ), cirq.Moment([cirq.Z(qubits[1]).with_tags(ops.VirtualTag())]), cirq.Moment( [ cirq.measure(qubits[0], key='q0'), cirq.measure(qubits[1], key='q1'), cirq.measure(qubits[2], key='q2'), ] ), ) _assert_equivalent_op_tree(expected_program, noisy_circuit)
def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): if _homogeneous_moment_is_measurements(moment) or self.is_virtual_moment(moment): # coverage: ignore return moment return [ moment, ops.Moment(self.qubit_noise_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits), ]
def noisy_moments(self, moments, system_qubits): result = [] for moment in moments: if moment.operations: result.append( cirq.X(moment.operations[0].qubits[0]).with_tags( ops.VirtualTag())) else: result.append([]) return result
def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): # Noise should not be appended to previously-added noise. if self.is_virtual_moment(moment): return moment return [ moment, ops.Moment( [self.qubit_noise_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits] ), ]
def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): if self.is_virtual_moment(moment): return moment if _homogeneous_moment_is_measurements(moment): return [ ops.Moment( self.readout_noise_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits), moment ] return moment
def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): if self.is_virtual_moment(moment): return moment if validate_all_measurements(moment): return [ ops.Moment( self.readout_decay_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits), moment, ] return moment
def test_constant_qubit_noise_prepend(): a, b, c = cirq.LineQubit.range(3) damp = cirq.amplitude_damp(0.5) damp_all = cirq.ConstantQubitNoiseModel(damp, prepend=True) actual = damp_all.noisy_moments( [cirq.Moment([cirq.X(a)]), cirq.Moment()], [a, b, c]) expected = [ [ cirq.Moment( d.with_tags(ops.VirtualTag()) for d in [damp(a), damp(b), damp(c)]), cirq.Moment([cirq.X(a)]), ], [ cirq.Moment( d.with_tags(ops.VirtualTag()) for d in [damp(a), damp(b), damp(c)]), cirq.Moment(), ], ] assert actual == expected cirq.testing.assert_equivalent_repr(damp_all)
def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): if self.is_virtual_moment(moment): return moment if validate_all_measurements(moment): output = [ circuits.Moment( self.readout_noise_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits), moment, ] return output if self._prepend else output[::-1] return moment
def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): if validate_all_measurements(moment) or self.is_virtual_moment(moment): # coverage: ignore return moment output = [ moment, circuits.Moment( self.qubit_noise_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits), ] return output[::-1] if self._prepend else output
def is_virtual_moment(self, moment: 'cirq.Moment') -> bool: """Returns true iff the given moment is non-empty and all of its operations are virtual. Moments for which this method returns True should not have additional noise applied to them. Args: moment: ``cirq.Moment`` to check for non-virtual operations. Returns: True if "moment" is non-empty and all operations in "moment" are virtual; false otherwise. """ if not moment.operations: return False return all(ops.VirtualTag() in op.tags for op in moment)
def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): # Noise should not be appended to previously-added noise. if self.is_virtual_moment(moment): return moment qbs = [] for op in moment.operations: if len(op.qubits) == 2: for qb in op.qubits: qbs.append(qb) return [ moment, ops.Moment([ # TODO: Replace with "VirtualTag" class instance. self.qubit_noise_gate(q).with_tags(ops.VirtualTag()) for q in qbs ]) ]
def noisy_operation(self, operation: 'cirq.Operation'): return cirq.Z(operation.qubits[0]).with_tags(ops.VirtualTag())
def noisy_moment(self, moment, system_qubits): return [ y.with_tags(ops.VirtualTag()) for y in cirq.Y.on_each(*moment.qubits) ]