r"""Return orthogonal permutation matrix for permutation tuple

    Return an orthogonal permutation matrix :math:`M_\sigma`
    for a permutation :math:`\sigma` defined by the image tuple
    :math:`(\sigma(1), \sigma(2),\dots \sigma(n))`,
    such that

    .. math::

        M_\sigma \vec{e}_i = \vec{e}_{\sigma(i)}

    where :math:`\vec{e}_k` is the k-th standard basis vector.
    This definition ensures a composition law:

    .. math::

        M_{\sigma \cdot \tau} = M_\sigma M_\tau.

    The column form of :math:`M_\sigma` is thus given by

    .. math::

        M = (
            \vec{e}_{\sigma(1)},
            \vec{e}_{\sigma(2)},
            \dots \vec{e}_{\sigma(n)}).

    Args:
        permutation (tuple): A permutation image tuple (zero-based indices!)

def permutation_matrix(permutation):
    r"""Return orthogonal permutation matrix for permutation tuple

    Return an orthogonal permutation matrix :math:`M_\sigma`
    for a permutation :math:`\sigma` defined by the image tuple
    :math:`(\sigma(1), \sigma(2),\dots \sigma(n))`,
    such that

    .. math::

        M_\sigma \vec{e}_i = \vec{e}_{\sigma(i)}

    where :math:`\vec{e}_k` is the k-th standard basis vector.
    This definition ensures a composition law:

    .. math::

        M_{\sigma \cdot \tau} = M_\sigma M_\tau.

    The column form of :math:`M_\sigma` is thus given by

    .. math::

        M = (
            \vec{e}_{\sigma(1)},
            \vec{e}_{\sigma(2)},
            \dots \vec{e}_{\sigma(n)}).

    Args:
        permutation (tuple): A permutation image tuple (zero-based indices!)
    """
    assert check_permutation(permutation)
    n = len(permutation)
    op_matrix = np_zeros((n, n), dtype=int)
    for i, j in enumerate(permutation):
        op_matrix[j, i] = 1
    return Matrix(op_matrix)