def apply_channel(self, action: Any, axes: Sequence[int], prng) -> int | None:
        """Apply channel to state.

        Args:
            action: The value with a channel to apply.
            axes: The axes on which to apply the channel.
            prng: The pseudo random number generator to use.
        Returns:
            The kraus index if the operation succeeded, otherwise None.
        """
        kraus_operators = protocols.kraus(action, default=None)
        if kraus_operators is None:
            return None

        def prepare_into_buffer(k: int):
            linalg.targeted_left_multiply(
                left_matrix=kraus_tensors[k],
                right_target=self._state_vector,
                target_axes=axes,
                out=self._buffer,
            )

        shape = protocols.qid_shape(action)
        kraus_tensors = [
            e.reshape(shape * 2).astype(self._state_vector.dtype) for e in kraus_operators
        ]
        p = prng.random()
        fallback_weight = 0.0
        fallback_weight_index = 0

        for index in range(len(kraus_tensors)):
            prepare_into_buffer(index)
            weight = float(np.linalg.norm(self._buffer) ** 2)

            if weight > fallback_weight:
                fallback_weight_index = index
                fallback_weight = weight

            p -= weight
            if p < 0:
                break

        assert weight is not None, "No Kraus operators"
        if p >= 0 or weight == 0:
            # Floating point error resulted in a malformed sample.
            # Fall back to the most likely case.
            prepare_into_buffer(fallback_weight_index)
            weight = fallback_weight
            index = fallback_weight_index

        self._buffer /= np.sqrt(weight)
        self._swap_target_tensor_for(self._buffer)
        return index
Apply channel to state.

        Args:
            action: The value with a channel to apply.
            axes: The axes on which to apply the channel.
            prng: The pseudo random number generator to use.
        Returns:
            The kraus index if the operation succeeded, otherwise None.
        
cirq-core/cirq/sim/state_vector_simulation_state.py