def is_transition_allowed(constraint_type: str, from_tag: str, from_entity:
    str, to_tag: str, to_entity: str):
    """
    Given a constraint type and strings ``from_tag`` and ``to_tag`` that
    represent the origin and destination of the transition, return whether
    the transition is allowed under the given constraint type.

    Parameters
    ----------
    constraint_type : ``str``, required
        Indicates which constraint to apply. Current choices are
        "BIO", "IOB1", "BIOUL", and "BMES".
    from_tag : ``str``, required
        The tag that the transition originates from. For example, if the
        label is ``I-PER``, the ``from_tag`` is ``I``.
    from_entity: ``str``, required
        The entity corresponding to the ``from_tag``. For example, if the
        label is ``I-PER``, the ``from_entity`` is ``PER``.
    to_tag : ``str``, required
        The tag that the transition leads to. For example, if the
        label is ``I-PER``, the ``to_tag`` is ``I``.
    to_entity: ``str``, required
        The entity corresponding to the ``to_tag``. For example, if the
        label is ``I-PER``, the ``to_entity`` is ``PER``.

    Returns
    -------
    ``bool``
        Whether the transition is allowed under the given ``constraint_type``.
    """
    if to_tag == 'START' or from_tag == 'END':
        return False
    if constraint_type == 'BIOUL':
        if from_tag == 'START':
            return to_tag in ('O', 'B', 'U')
        if to_tag == 'END':
            return from_tag in ('O', 'L', 'U')
        return any([from_tag in ('O', 'L', 'U') and to_tag in ('O', 'B',
            'U'), from_tag in ('B', 'I') and to_tag in ('I', 'L') and 
            from_entity == to_entity])
    elif constraint_type == 'BIO':
        if from_tag == 'START':
            return to_tag in ('O', 'B')
        if to_tag == 'END':
            return from_tag in ('O', 'B', 'I')
        return any([to_tag in ('O', 'B'), to_tag == 'I' and from_tag in (
            'B', 'I') and from_entity == to_entity])
    elif constraint_type == 'IOB1':
        if from_tag == 'START':
            return to_tag in ('O', 'I')
        if to_tag == 'END':
            return from_tag in ('O', 'B', 'I')
        return any([to_tag in ('O', 'I'), to_tag == 'B' and from_tag in (
            'B', 'I') and from_entity == to_entity])
    elif constraint_type == 'BMES':
        if from_tag == 'START':
            return to_tag in ('B', 'S')
        if to_tag == 'END':
            return from_tag in ('E', 'S')
        return any([to_tag in ('B', 'S') and from_tag in ('E', 'S'), to_tag ==
            'M' and from_tag in ('B', 'M') and from_entity == to_entity, 
            to_tag == 'E' and from_tag in ('B', 'M') and from_entity ==
            to_entity])
    else:
        raise f'Unknown constraint type: {constraint_type}'
