def _apply_kraus_multi_qubit(
    kraus: tuple[Any] | Sequence[Any], args: ApplyChannelArgs
) -> np.ndarray:
    """Use numpy's einsum to apply a multi-qubit channel."""
    qid_shape = tuple(args.target_tensor.shape[i] for i in args.left_axes)
    for kraus_op in kraus:
        np.copyto(dst=args.target_tensor, src=args.auxiliary_buffer0)
        kraus_tensor = np.reshape(kraus_op.astype(args.target_tensor.dtype), qid_shape * 2)
        linalg.targeted_left_multiply(
            kraus_tensor, args.target_tensor, args.left_axes, out=args.auxiliary_buffer1
        )
        # No need to transpose as we are acting on the tensor
        # representation of matrix, so transpose is done for us.
        linalg.targeted_left_multiply(
            np.conjugate(kraus_tensor),
            args.auxiliary_buffer1,
            args.right_axes,
            out=args.target_tensor,
        )
        args.out_buffer += args.target_tensor
    return args.out_buffer
Use numpy's einsum to apply a multi-qubit channel.
cirq-core/cirq/protocols/apply_channel_protocol.py