def __init__(self, p) -> None: r"""The phase flip channel. Construct a channel to flip the phase with probability p. This channel evolves a density matrix via: $$ \rho \rightarrow M_0 \rho M_0^\dagger + M_1 \rho M_1^\dagger $$ With: $$ \begin{aligned} M_0 =& \sqrt{1 - p} \begin{bmatrix} 1 & 0 \\ 0 & 1 \end{bmatrix} \\ M_1 =& \sqrt{p} \begin{bmatrix} 1 & 0 \\ 0 & -1 \end{bmatrix} \end{aligned} $$ Args: p: the probability of a phase flip. Raises: ValueError: if p is not a valid probability. """ self._p = value.validate_probability(p, 'p') self._delegate = AsymmetricDepolarizingChannel(0., 0., p)
def __init__(self, gamma) -> None: r"""The phase damping channel. Construct a channel that enacts a phase damping constant gamma. This channel evolves a density matrix via: $$ \rho \rightarrow M_0 \rho M_0^\dagger + M_1 \rho M_1^\dagger $$ With: $$ \begin{aligned} M_0 =& \begin{bmatrix} 1 & 0 \\ 0 & \sqrt{1 - \gamma} \end{bmatrix} \\ M_1 =& \begin{bmatrix} 0 & 0 \\ 0 & \sqrt{\gamma} \end{bmatrix} \end{aligned} $$ Args: gamma: The damping constant. Raises: ValueError: if gamma is not a valid probability. """ self._gamma = value.validate_probability(gamma, 'gamma')
def __init__(self, depol_prob: float, bitflip_prob: float, decay_prob: float): """A depolarizing noise model with damped readout error. Args: depol_prob: Depolarizing probability. bitflip_prob: Probability of a bit-flip during measurement. decay_prob: Probability of T1 decay during measurement. Bitflip noise is applied first, then amplitude decay. """ value.validate_probability(depol_prob, 'depol prob') value.validate_probability(bitflip_prob, 'bitflip prob') value.validate_probability(decay_prob, 'decay_prob') self.qubit_noise_gate = ops.DepolarizingChannel(depol_prob) self.readout_noise_gate = ops.BitFlipChannel(bitflip_prob) self.readout_decay_gate = ops.AmplitudeDampingChannel(decay_prob)
def __init__(self, gamma: float) -> None: r"""The amplitude damping channel. Construct a channel that dissipates energy. The probability of energy exchange occurring is given by gamma. This channel evolves a density matrix as follows: $$ \rho \rightarrow M_0 \rho M_0^\dagger + M_1 \rho M_1^\dagger $$ With: $$ \begin{aligned} M_0 =& \begin{bmatrix} 1 & 0 \\ 0 & \sqrt{1 - \gamma} \end{bmatrix} \\ M_1 =& \begin{bmatrix} 0 & \sqrt{\gamma} \\ 0 & 0 \end{bmatrix} \end{aligned} $$ Args: gamma: the probability of the interaction being dissipative. Raises: ValueError: is gamma is not a valid probability. """ self._gamma = value.validate_probability(gamma, 'gamma') self._delegate = GeneralizedAmplitudeDampingChannel(1.0, self._gamma)
def __init__(self, p_x: Optional[float] = None, p_y: Optional[float] = None, p_z: Optional[float] = None, error_probabilities: Optional[Dict[str, float]] = None, tol: float = 1e-8) -> None: r"""The asymmetric depolarizing channel. This channel applies one of 4**n disjoint possibilities: nothing (the identity channel) or one of the 4**n - 1 pauli gates. This channel evolves a density matrix via $$ \sum_i p_i Pi \rho Pi $$ where i varies from 0 to 4**n-1 and Pi represents n-qubit Pauli operator (including identity). The input $\rho$ is the density matrix before the depolarization. Args: p_x: The probability that a Pauli X and no other gate occurs. p_y: The probability that a Pauli Y and no other gate occurs. p_z: The probability that a Pauli Z and no other gate occurs. error_probabilities: Dictionary of string (Pauli operator) to its probability. If the identity is missing from the list, it will be added so that the total probability mass is 1. tol: The tolerance used making sure the total probability mass is equal to 1. Examples of calls: * Single qubit: AsymmetricDepolarizingChannel(0.2, 0.1, 0.3) * Single qubit: AsymmetricDepolarizingChannel(p_z=0.3) * Two qubits: AsymmetricDepolarizingChannel( error_probabilities={'XX': 0.2}) Raises: ValueError: if the args or the sum of args are not probabilities. """ if error_probabilities: num_qubits = len(list(error_probabilities)[0]) for k in error_probabilities.keys(): if not set(k).issubset({'I', 'X', 'Y', 'Z'}): raise ValueError(f"{k} is not made solely of I, X, Y, Z.") if len(k) != num_qubits: raise ValueError( f"{k} must have {num_qubits} Pauli gates.") for k, v in error_probabilities.items(): value.validate_probability(v, f"p({k})") sum_probs = sum(error_probabilities.values()) identity = 'I' * num_qubits if sum_probs < 1.0 - tol and identity not in error_probabilities: error_probabilities[identity] = 1.0 - sum_probs elif abs(sum_probs - 1.0) > tol: raise ValueError( f"Probabilities do not add up to 1 but to {sum_probs}") self._num_qubits = num_qubits self._error_probabilities = error_probabilities else: p_x = 0.0 if p_x is None else p_x p_y = 0.0 if p_y is None else p_y p_z = 0.0 if p_z is None else p_z p_x = value.validate_probability(p_x, 'p_x') p_y = value.validate_probability(p_y, 'p_y') p_z = value.validate_probability(p_z, 'p_z') p_i = 1 - value.validate_probability(p_x + p_y + p_z, 'p_x + p_y + p_z') self._num_qubits = 1 self._error_probabilities = { 'I': p_i, 'X': p_x, 'Y': p_y, 'Z': p_z }
def __init__( self, p_x: Optional[float] = None, p_y: Optional[float] = None, p_z: Optional[float] = None, error_probabilities: Optional[Dict[str, float]] = None) -> None: r"""The asymmetric depolarizing channel. This channel applies one of 4**n disjoint possibilities: nothing (the identity channel) or one of the 4**n - 1 pauli gates. This channel evolves a density matrix via $$ \sum_i p_i Pi \rho Pi $$ where i varies from 0 to 4**n-1 and Pi represents n-qubit Pauli operator (including identity). The input \rho is the density matrix before the depolarization. Args: p_x: The probability that a Pauli X and no other gate occurs. p_y: The probability that a Pauli Y and no other gate occurs. p_z: The probability that a Pauli Z and no other gate occurs. error_probabilities: Dictionary of string (Pauli operator) to its probability Examples of calls: * Single qubit: AsymmetricDepolarizingChannel(0.2, 0.1, 0.3) * Single qubit: AsymmetricDepolarizingChannel(p_z=0.3) * Two qubits: AsymmetricDepolarizingChannel( error_probabilities={'XX': 0.2}) Raises: ValueError: if the args or the sum of args are not probabilities. """ if error_probabilities: num_qubits = len(list(error_probabilities)[0]) for k in error_probabilities.keys(): if not set(k).issubset({'I', 'X', 'Y', 'Z'}): raise ValueError(f"{k} is not made solely of I, X, Y, Z.") if len(k) != num_qubits: raise ValueError( f"{k} must have {num_qubits} Pauli gates.") for k, v in error_probabilities.items(): value.validate_probability(v, f"p({k})") value.validate_probability(sum(error_probabilities.values()), 'sum(error_probabilities)') self._num_qubits = num_qubits self._error_probabilities = error_probabilities else: p_x = 0.0 if p_x is None else p_x p_y = 0.0 if p_y is None else p_y p_z = 0.0 if p_z is None else p_z p_x = value.validate_probability(p_x, 'p_x') p_y = value.validate_probability(p_y, 'p_y') p_z = value.validate_probability(p_z, 'p_z') p_i = 1 - value.validate_probability(p_x + p_y + p_z, 'p_x + p_y + p_z') self._num_qubits = 1 self._error_probabilities = { 'I': p_i, 'X': p_x, 'Y': p_y, 'Z': p_z }
def __init__(self, p_xi: float, p_yi: float, p_zi: float, p_xx: float, p_yx: float, p_zx: float, p_xy: float, p_yy: float, p_zy: float, p_xz: float, p_yz: float, p_zz: float, p_ix: float, p_iy: float, p_iz: float) -> None: r"""The asymmetric depolarizing channel. This channel applies one of 16 disjoint possibilities: nothing (the identity channel) or a combination of the three pauli gates and the identity on each of two qubits. The disjoint probabilities of the 15 gates are p_xi, p_xx, and p_xy, p_xz, and so on. The identity is done with probability 1 - sum(p_jk), where j is the operation on the first qubit and k is the operation on the second. The supplied probabilities must be valid probabilities and the sum p_jk must be a valid probability or else this constructor will raise a ValueError. This channel evolves a density matrix via $$ \rho \rightarrow (1 - \Sum_{jk} p_jk) \rho + \Sum_{jk} p_jk j \otimes k $$ Args: p_xi: The probability that a Pauli X on qubit 1 and no other gate occurs. p_yi: The probability that a Pauli Y on qubit 1 and no other gate occurs. p_zi: The probability that a Pauli Z on qubit 1 and no other gate occurs. p_xx: The probability that a Pauli X on qubit 1 and a Pauli X on qubit 2 occurs. p_yx: The probability that a Pauli Y on qubit 1 and a Pauli Y on qubit 2 occurs. p_zx: The probability that a Pauli Z on qubit 1 and a Pauli Z on qubit 2 occurs. p_xy: The probability that a Pauli X on qubit 1 and a Pauli X on qubit 2 occurs. p_yy: The probability that a Pauli Y on qubit 1 and a Pauli Y on qubit 2 occurs. p_zy: The probability that a Pauli Z on qubit 1 and a Pauli Z on qubit 2 occurs. p_xz: The probability that a Pauli X on qubit 1 and a Pauli X on qubit 2 occurs. p_yz: The probability that a Pauli Y on qubit 1 and a Pauli Y on qubit 2 occurs. p_zz: The probability that a Pauli Z on qubit 1 and a Pauli Z on qubit 2 occurs. Raises: ValueError: if the args or the sum of args are not probabilities. """ self._p_xi = value.validate_probability(p_xi, 'p_xi') self._p_yi = value.validate_probability(p_yi, 'p_yi') self._p_zi = value.validate_probability(p_zi, 'p_zi') self._p_xx = value.validate_probability(p_xx, 'p_xx') self._p_yx = value.validate_probability(p_yx, 'p_yx') self._p_zx = value.validate_probability(p_zx, 'p_zx') self._p_xy = value.validate_probability(p_xy, 'p_xy') self._p_yy = value.validate_probability(p_yy, 'p_yy') self._p_zy = value.validate_probability(p_zy, 'p_zy') self._p_xz = value.validate_probability(p_xz, 'p_xz') self._p_yz = value.validate_probability(p_yz, 'p_yz') self._p_zz = value.validate_probability(p_zz, 'p_zz') self._p_ix = value.validate_probability(p_ix, 'p_ix') self._p_iy = value.validate_probability(p_iy, 'p_iy') self._p_iz = value.validate_probability(p_iz, 'p_iz') self._p_ii = 1 - value.validate_probability( p_xi + p_yi + p_zi + p_xx + p_yx + p_zx + p_xy + p_yy + p_zy + p_xz + p_yz + p_zz + p_ix + p_iy + p_iz, 'p_ii')