Beispiel #1
0
def from_set(left: '( M )', *values: '( M )') -> 'PP(M x M)':
    """Return a clan where all relations contain a single couplet with the same left component.

    :param left: The :term:`left component` of all :term:`couplet`\s in the returned :term:`clan`.
    :param values: The :term:`right component`\s of the couplets in the returned clan.
    :return: A clan where every :term:`relation` consists of a single couplet with a left component
        of ``left`` and a right component from ``values``.
    """
    left_mo = _mo.auto_convert(left)
    clan = _mo.Set((_mo.Set(_mo.Couplet(left_mo, _mo.auto_convert(right), direct_load=True),
                            direct_load=True).cache_is_relation(True)
                    for right in values), direct_load=True).cache_is_clan(True)
    return clan
Beispiel #2
0
def get_rights_for_left(mclan: 'P(P(M x M) x N)', left: '( M )', _checked=True) -> 'P(M x N)':
    """Return the multiset of the right components of all couplets in the multiclan ``mclan``
    associated with the left component ``left``.

    :return: The :term:`right multiset` of the :term:`multiclan` ``mclan`` associated with the
        :term:`left component` ``left`` or `Undef()` if ``mclan`` is not a multiclan.
    """
    if _checked:
        if not is_member(mclan):
            return _undef.make_or_raise_undef2(mclan)
        if left is _undef.Undef():
            return _mo.Set()
        left = _mo.auto_convert(left)
    else:
        assert is_member_or_undef(mclan)
        assert _mo.is_mathobject_or_undef(left)
        if mclan is _undef.Undef():
            return _undef.make_or_raise_undef(2)
        if left is _undef.Undef():
            return _mo.Set()
    clan_itr = iter(mclan)
    rights = _sets.multify(_relations.get_rights_for_left(next(clan_itr), left, _checked=False))
    for rel in clan_itr:
        rights = _multisets.add(
            _sets.multify(_relations.get_rights_for_left(rel, left, _checked=False)),
            rights, _checked=False)
    if not rights.is_empty:
        if mclan.cached_is_absolute:
            rights.cache_absolute(_mo.CacheStatus.IS)
    return rights
Beispiel #3
0
def get_left(rel: 'P(M x M)', right: '( M )', _checked=True) -> '( M )':
    r"""Return the left component of the couplet that has a right component of ``right``.

    In general, use with :term:`right-functional` :term:`relation`\s; that is, relations
    where all :term:`right component`\s appear at most once.

    :return: The :term:`left component` of the :term:`couplet` that has a :term:`right component`
        of ``right``, or `Undef()` if there is not exactly one couplet with the right component
        ``right`` in ``rel`` or ``rel`` is not a :term:`relation`.
    """
    if _checked:
        if not is_member(rel):
            return _undef.make_or_raise_undef2(rel)
        if right is _undef.Undef():
            return _undef.make_or_raise_undef(2)
        right = _mo.auto_convert(right)
    else:
        assert is_member_or_undef(rel)
        assert _mo.is_mathobject_or_undef(right)
        if right is _undef.Undef() or rel is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    result = None
    for elem in rel:
        assert elem.is_couplet
        if elem.right == right:
            if result is not None:
                return _undef.make_or_raise_undef()  # Early Undef() exit if more than one found.
            result = elem.left
    if result is None:
        return _undef.make_or_raise_undef()  # Undef() exit if none found.
    return result
Beispiel #4
0
def get_rights_for_left(rel: 'P(M x M)', left: '( M )', _checked=True) -> 'P( M )':
    """Return the set of the right components of all couplets in the relation ``rel`` associated
    with the :term:`left component` ``left``.

    :return: The :term:`right set` of the :term:`relation` ``rel`` associated with the :term:`left
        component` or `Undef()` if ``rel`` is not a :term:`relation`.
    """
    if _checked:
        if not is_member(rel):
            return _undef.make_or_raise_undef2(rel)
        if left is _undef.Undef():
            return _mo.Set()
        left = _mo.auto_convert(left)
    else:
        assert is_member_or_undef(rel)
        assert _mo.is_mathobject_or_undef(left)
        if rel is _undef.Undef():
            return _undef.make_or_raise_undef(2)
        if left is _undef.Undef():
            return _mo.Set()
    result = _mo.Set((elem.right for elem in rel if elem.left == left), direct_load=True)
    if not result.is_empty:
        if rel.cached_is_absolute:
            result.cache_absolute(_mo.CacheStatus.IS)
    return result
Beispiel #5
0
def get_rights_for_left(mclan: 'P(P(M x M) x N)',
                        left: '( M )',
                        _checked=True) -> 'P(M x N)':
    """Return the multiset of the right components of all couplets in the multiclan ``mclan``
    associated with the left component ``left``.

    :return: The :term:`right multiset` of the :term:`multiclan` ``mclan`` associated with the
        :term:`left component` ``left`` or `Undef()` if ``mclan`` is not a multiclan.
    """
    if _checked:
        if not is_member(mclan):
            return _undef.make_or_raise_undef2(mclan)
        if left is _undef.Undef():
            return _mo.Set()
        left = _mo.auto_convert(left)
    else:
        assert is_member_or_undef(mclan)
        assert _mo.is_mathobject_or_undef(left)
        if mclan is _undef.Undef():
            return _undef.make_or_raise_undef(2)
        if left is _undef.Undef():
            return _mo.Set()
    clan_itr = iter(mclan)
    rights = _sets.multify(
        _relations.get_rights_for_left(next(clan_itr), left, _checked=False))
    for rel in clan_itr:
        rights = _multisets.add(_sets.multify(
            _relations.get_rights_for_left(rel, left, _checked=False)),
                                rights,
                                _checked=False)
    if not rights.is_empty:
        if mclan.cached_is_absolute:
            rights.cache_absolute(_mo.CacheStatus.IS)
    return rights
Beispiel #6
0
def get_left(rel: 'P(M x M)', right: '( M )', _checked=True) -> '( M )':
    """Return the single :term:`left component` associated with the :term:`right component` ``right``.

    In general, use with :term:`right-functional` :term:`relation`\s; that is, relations
    where all right components appear at most once.

    :return: The single :term:`left component` associated with the :term:`right component`
        ``right``, or `Undef()` if there is not exactly one element with the right component
        ``right`` in ``rel`` or ``rel`` is not a :term:`relation`.
    """
    if _checked:
        if not is_member(rel):
            return _make_or_raise_undef()
    else:
        assert is_member(rel)
    right = _mo.auto_convert(right)
    result = None
    for elem in rel:
        assert isinstance(elem, _mo.Couplet)
        if elem.right == right:
            if result is not None:
                return _make_or_raise_undef()  # Early Undef() exit if more than one found.
            result = elem.left
    if result is None:
        return _make_or_raise_undef()  # Undef() exit if none found.
    return result
Beispiel #7
0
def get_left(rel: 'P(M x M)', right: '( M )', _checked=True) -> '( M )':
    r"""Return the left component of the couplet that has a right component of ``right``.

    In general, use with :term:`right-functional` :term:`relation`\s; that is, relations
    where all :term:`right component`\s appear at most once.

    :return: The :term:`left component` of the :term:`couplet` that has a :term:`right component`
        of ``right``, or `Undef()` if there is not exactly one couplet with the right component
        ``right`` in ``rel`` or ``rel`` is not a :term:`relation`.
    """
    if _checked:
        if not is_member(rel):
            return _undef.make_or_raise_undef2(rel)
        if right is _undef.Undef():
            return _undef.make_or_raise_undef(2)
        right = _mo.auto_convert(right)
    else:
        assert is_member_or_undef(rel)
        assert _mo.is_mathobject_or_undef(right)
        if right is _undef.Undef() or rel is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    result = None
    for elem in rel:
        assert elem.is_couplet
        if elem.right == right:
            if result is not None:
                return _undef.make_or_raise_undef(
                )  # Early Undef() exit if more than one found.
            result = elem.left
    if result is None:
        return _undef.make_or_raise_undef()  # Undef() exit if none found.
    return result
Beispiel #8
0
def get_rights_for_left(rel: 'P(M x M)',
                        left: '( M )',
                        _checked=True) -> 'P( M )':
    """Return the set of the right components of all couplets in the relation ``rel`` associated
    with the :term:`left component` ``left``.

    :return: The :term:`right set` of the :term:`relation` ``rel`` associated with the :term:`left
        component` or `Undef()` if ``rel`` is not a :term:`relation`.
    """
    if _checked:
        if not is_member(rel):
            return _undef.make_or_raise_undef2(rel)
        if left is _undef.Undef():
            return _mo.Set()
        left = _mo.auto_convert(left)
    else:
        assert is_member_or_undef(rel)
        assert _mo.is_mathobject_or_undef(left)
        if rel is _undef.Undef():
            return _undef.make_or_raise_undef(2)
        if left is _undef.Undef():
            return _mo.Set()
    result = _mo.Set((elem.right for elem in rel if elem.left == left),
                     direct_load=True)
    if not result.is_empty:
        if rel.cached_is_absolute:
            result.cache_absolute(_mo.CacheStatus.IS)
    return result
Beispiel #9
0
def from_set(left: '( M )', *values: '( M )') -> 'PP(M x M)':
    r"""Return a clan where all relations contain a single couplet with the same left component.

    :param left: The :term:`left component` of all :term:`couplet`\s in the returned :term:`clan`.
    :param values: The :term:`right component`\s of the couplets in the returned clan. (If you want
        to pass in an iterable, you need to prefix it with an asterisk ``*``.)
    :return: A clan where every :term:`relation` consists of a single couplet with a left component
        of ``left`` and a right component from ``values``.
    """
    left_mo = _mo.auto_convert(left)
    clan = _mo.Set(
        (_mo.Set(_mo.Couplet(left_mo, _mo.auto_convert(right), direct_load=True), direct_load=True)
            .cache_relation(_mo.CacheStatus.IS)
            .cache_functional(_mo.CacheStatus.IS).cache_right_functional(_mo.CacheStatus.IS)
            for right in values),
        direct_load=True)
    clan.cache_clan(_mo.CacheStatus.IS)
    clan.cache_functional(_mo.CacheStatus.IS).cache_right_functional(_mo.CacheStatus.IS)
    clan.cache_regular(_mo.CacheStatus.IS).cache_right_regular(_mo.CacheStatus.IS)
    return clan
Beispiel #10
0
def from_set(left: '( M )', *values: '( M )') -> 'PP(M x M)':
    r"""Return a clan where all relations contain a single couplet with the same left component.

    :param left: The :term:`left component` of all :term:`couplet`\s in the returned :term:`clan`.
    :param values: The :term:`right component`\s of the couplets in the returned clan. (If you want
        to pass in an iterable, you need to prefix it with an asterisk ``*``.)
    :return: A clan where every :term:`relation` consists of a single couplet with a left component
        of ``left`` and a right component from ``values``.
    """
    left_mo = _mo.auto_convert(left)
    clan = _mo.Set((_mo.Set(
        _mo.Couplet(left_mo, _mo.auto_convert(right), direct_load=True),
        direct_load=True).cache_relation(CacheStatus.IS).cache_functional(
            CacheStatus.IS).cache_right_functional(CacheStatus.IS)
                    for right in values),
                   direct_load=True)
    clan.cache_clan(CacheStatus.IS)
    clan.cache_functional(CacheStatus.IS).cache_right_functional(
        CacheStatus.IS)
    clan.cache_regular(CacheStatus.IS).cache_right_regular(CacheStatus.IS)
    return clan
Beispiel #11
0
def _create_partition_dict_from_set(set_, class_invariant_func):
    r"""Return the data of a partition defined by ``class_invariant_func`` on ``set_``.

    :param set_: The :term:`set` to be partitioned.
    :param class_invariant_func: A function from ``set_`` to :term:`set M`.
    :return: A ``dict`` of ``set``\s, where the keys of the ``dict`` are the range of the
        equivalence relation implemented by ``class_invariant_func`` and the ``set``\s are the
        members of ``set_`` that are associated with each given key. Both the keys and the members
        of the value ``set``\s are `MathObject`\s.
    """
    # Collect the data of the partition in a dictionary of sets.
    partition_dict = {}

    for element in set_:
        # equivalence_class must be a MathObject.
        equivalence_class = _mo.auto_convert(class_invariant_func(element))

        # equivalence_class is a MathObject, so it is hashable and can be used as dict key.
        if equivalence_class not in partition_dict:
            partition_dict[equivalence_class] = set()
        partition_dict[equivalence_class].add(element)

    return partition_dict
Beispiel #12
0
def _create_partition_dict_from_multiset(mset, class_invariant_func):
    r"""Return the data of a partition defined by ``class_invariant_func`` on ``mset``.

    :param mset: The :term:`multiset` to be partitioned.
    :param class_invariant_func: A function from ``mset`` to :term:`set M`.
    :return: A ``dict`` of :class:`~collection.Counter`\s, where the keys of the ``dict`` are the
        range of the equivalence relation implemented by ``class_invariant_func`` and the
        ``Counter``\s are the members of ``mset`` that are associated with each given key. Both
        the keys and the value members of the ``Counter``\s are `MathObject`\s.
    """

    # Collect the data of the partition in a dictionary of Counters.
    partition_dict = {}

    for element, count in mset.data.items():
        # equivalence_class must be a MathObject.
        equivalence_class = _mo.auto_convert(class_invariant_func(element))

        # equivalence_class is a MathObject, so it is hashable and can be used as dict key.
        if equivalence_class not in partition_dict:
            partition_dict[equivalence_class] = _collections.Counter()
        partition_dict[equivalence_class][element] = count

    return partition_dict
Beispiel #13
0
def _create_partition_dict(set1, equivalence_relation):
    """Return the data of a partition defined by ``equivalence_relation`` on ``set1``.

    :param set1: The :term:`set` to be partitioned.
    :param equivalence_relation: A function from ``set1`` to :term:`set M`.
    :return: A ``dict`` of ``set``\s, where the keys of the ``dict`` are the range of the
        equivalence relation implemented by ``equivalence_relation`` and the ``set``\s are the
        members of ``set1`` that are associated with each given key.
    """

    # Collect the data of the partition in a dictionary of lists, which later is converted into a
    # Set of Sets.
    partition_dict = {}

    for element in set1:
        # equivalence_class must be a MathObject.
        equivalence_class = _mo.auto_convert(equivalence_relation(element))

        # equivalence_class is a MathObject, so it is hashable and can be used as dict key.
        if equivalence_class not in partition_dict:
            partition_dict[equivalence_class] = set()
        partition_dict[equivalence_class].add(element)

    return partition_dict