1# Copyright 2019 The Cirq Developers 2# 3# Licensed under the Apache License, Version 2.0 (the "License"); 4# you may not use this file except in compliance with the License. 5# You may obtain a copy of the License at 6# 7# https://www.apache.org/licenses/LICENSE-2.0 8# 9# Unless required by applicable law or agreed to in writing, software 10# distributed under the License is distributed on an "AS IS" BASIS, 11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12# See the License for the specific language governing permissions and 13# limitations under the License. 14 15from typing import Sequence, TYPE_CHECKING 16 17from cirq import devices, value, ops 18from cirq.devices.noise_model import validate_all_measurements 19 20if TYPE_CHECKING: 21 import cirq 22 23 24class DepolarizingNoiseModel(devices.NoiseModel): 25 """Applies depolarizing noise to each qubit individually at the end of 26 every moment. 27 28 If a circuit contains measurements, they must be in moments that don't 29 also contain gates. 30 """ 31 32 def __init__(self, depol_prob: float): 33 """A depolarizing noise model 34 35 Args: 36 depol_prob: Depolarizing probability. 37 """ 38 value.validate_probability(depol_prob, 'depol prob') 39 self.qubit_noise_gate = ops.DepolarizingChannel(depol_prob) 40 41 def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): 42 if validate_all_measurements(moment) or self.is_virtual_moment(moment): 43 # coverage: ignore 44 return moment 45 46 return [ 47 moment, 48 ops.Moment(self.qubit_noise_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits), 49 ] 50 51 52class ReadoutNoiseModel(devices.NoiseModel): 53 """NoiseModel with probabilistic bit flips preceding measurement. 54 55 This simulates readout error. Note that since noise is applied before the 56 measurement moment, composing this model on top of another noise model will 57 place the bit flips immediately before the measurement (regardless of the 58 previously-added noise). 59 60 If a circuit contains measurements, they must be in moments that don't 61 also contain gates. 62 """ 63 64 def __init__(self, bitflip_prob: float): 65 """A noise model with readout error. 66 67 Args: 68 bitflip_prob: Probability of a bit-flip during measurement. 69 """ 70 value.validate_probability(bitflip_prob, 'bitflip prob') 71 self.readout_noise_gate = ops.BitFlipChannel(bitflip_prob) 72 73 def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): 74 if self.is_virtual_moment(moment): 75 return moment 76 if validate_all_measurements(moment): 77 return [ 78 ops.Moment( 79 self.readout_noise_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits 80 ), 81 moment, 82 ] 83 return moment 84 85 86class DampedReadoutNoiseModel(devices.NoiseModel): 87 """NoiseModel with T1 decay preceding measurement. 88 89 This simulates asymmetric readout error. Note that since noise is applied 90 before the measurement moment, composing this model on top of another noise 91 model will place the T1 decay immediately before the measurement 92 (regardless of the previously-added noise). 93 94 If a circuit contains measurements, they must be in moments that don't 95 also contain gates. 96 """ 97 98 def __init__(self, decay_prob: float): 99 """A depolarizing noise model with damped readout error. 100 101 Args: 102 decay_prob: Probability of T1 decay during measurement. 103 """ 104 value.validate_probability(decay_prob, 'decay_prob') 105 self.readout_decay_gate = ops.AmplitudeDampingChannel(decay_prob) 106 107 def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): 108 if self.is_virtual_moment(moment): 109 return moment 110 if validate_all_measurements(moment): 111 return [ 112 ops.Moment( 113 self.readout_decay_gate(q).with_tags(ops.VirtualTag()) for q in system_qubits 114 ), 115 moment, 116 ] 117 return moment 118 119 120class DepolarizingWithReadoutNoiseModel(devices.NoiseModel): 121 """DepolarizingNoiseModel with probabilistic bit flips preceding 122 measurement. 123 This simulates readout error. 124 If a circuit contains measurements, they must be in moments that don't 125 also contain gates. 126 """ 127 128 def __init__(self, depol_prob: float, bitflip_prob: float): 129 """A depolarizing noise model with readout error. 130 Args: 131 depol_prob: Depolarizing probability. 132 bitflip_prob: Probability of a bit-flip during measurement. 133 """ 134 value.validate_probability(depol_prob, 'depol prob') 135 value.validate_probability(bitflip_prob, 'bitflip prob') 136 self.qubit_noise_gate = ops.DepolarizingChannel(depol_prob) 137 self.readout_noise_gate = ops.BitFlipChannel(bitflip_prob) 138 139 def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): 140 if validate_all_measurements(moment): 141 return [ 142 ops.Moment(self.readout_noise_gate(q) for q in system_qubits), 143 moment, 144 ] 145 return [ 146 moment, 147 ops.Moment(self.qubit_noise_gate(q) for q in system_qubits), 148 ] 149 150 151class DepolarizingWithDampedReadoutNoiseModel(devices.NoiseModel): 152 """DepolarizingWithReadoutNoiseModel with T1 decay preceding 153 measurement. 154 This simulates asymmetric readout error. The noise is structured 155 so the T1 decay is applied, then the readout bitflip, then measurement. 156 If a circuit contains measurements, they must be in moments that don't 157 also contain gates. 158 """ 159 160 def __init__( 161 self, 162 depol_prob: float, 163 bitflip_prob: float, 164 decay_prob: float, 165 ): 166 """A depolarizing noise model with damped readout error. 167 Args: 168 depol_prob: Depolarizing probability. 169 bitflip_prob: Probability of a bit-flip during measurement. 170 decay_prob: Probability of T1 decay during measurement. 171 Bitflip noise is applied first, then amplitude decay. 172 """ 173 value.validate_probability(depol_prob, 'depol prob') 174 value.validate_probability(bitflip_prob, 'bitflip prob') 175 value.validate_probability(decay_prob, 'decay_prob') 176 self.qubit_noise_gate = ops.DepolarizingChannel(depol_prob) 177 self.readout_noise_gate = ops.BitFlipChannel(bitflip_prob) 178 self.readout_decay_gate = ops.AmplitudeDampingChannel(decay_prob) 179 180 def noisy_moment(self, moment: 'cirq.Moment', system_qubits: Sequence['cirq.Qid']): 181 if validate_all_measurements(moment): 182 return [ 183 ops.Moment(self.readout_decay_gate(q) for q in system_qubits), 184 ops.Moment(self.readout_noise_gate(q) for q in system_qubits), 185 moment, 186 ] 187 else: 188 return [moment, ops.Moment(self.qubit_noise_gate(q) for q in system_qubits)] 189