def __init__(
        self,
        p_x: float | None = None,
        p_y: float | None = None,
        p_z: float | None = None,
        error_probabilities: dict[str, float] | None = None,
        tol: float = 1e-8,
    ) -> None:
        r"""The asymmetric depolarizing channel.

        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}
The asymmetric depolarizing channel.

        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.
        
cirq-core/cirq/ops/common_channels.py