Пример #1
0
    def cross_functional_union(mclan1: 'P(P(M x M) x N)',
                               mclan2: 'P(P(M x M) x N)',
                               _checked=True) -> 'P(P(M x M) x N)':
        r"""Return the :term:`cross-functional union` of ``mclan1`` and ``mclan2``.

        :return: The :term:`binary multi-extension` of the :term:`functional union` from the
            :term:`algebra of relations` to the :term:`algebra of multiclans`, applied to
            ``mclan1`` and ``mclan2``, or `Undef()` if ``mclan1`` or ``mclan2`` are
            not :term:`multiclan`\s.
        """
        if _checked:
            if not is_member(mclan1):
                return _undef.make_or_raise_undef2(mclan1)
            if not is_member(mclan2):
                return _undef.make_or_raise_undef2(mclan2)
        else:
            assert is_member_or_undef(mclan1)
            assert is_member_or_undef(mclan2)
            if mclan1 is _undef.Undef() or mclan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_multi_extend(
            mclan1,
            mclan2,
            _functools.partial(_relations.functional_union, _checked=False),
            _checked=False)
        if not result.is_empty:
            result.cache_multiclan(CacheStatus.IS)
            result.cache_functional(CacheStatus.IS)
            if mclan1.cached_is_not_right_functional or mclan2.cached_is_not_right_functional:
                result.cache_right_functional(CacheStatus.IS_NOT)
        return result
Пример #2
0
    def right_functional_union(rel1: 'P(M x M)',
                               rel2: 'P(M x M)',
                               _checked=True) -> 'P(M x M)':
        r"""Return the union of ``rel1`` and ``rel2`` if it is right-functional, otherwise
        `Undef()`.

        :return: The :term:`right-functional union` of the :term:`relation`\s ``rel1`` and
            ``rel2``; that is, the :term:`union` if the result is :term:`right-functional`,
            otherwise `Undef()`. Also return `Undef()` if ``rel1`` or ``rel2`` are not relations.
        """
        if _checked:
            if not is_member(rel1):
                return _undef.make_or_raise_undef2(rel1)
            if not is_member(rel2):
                return _undef.make_or_raise_undef2(rel2)
        else:
            assert is_member_or_undef(rel1)
            assert is_member_or_undef(rel2)
            if rel1 is _undef.Undef() or rel2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        rel_union = _sets.union(rel1, rel2, _checked=False).cache_relation(
            _mo.CacheStatus.IS)
        if not is_right_functional(rel_union, _checked=False):
            return _undef.make_or_raise_undef(2)
        return rel_union
Пример #3
0
    def cross_intersect(clan1: 'PP(M x M)', clan2: 'PP(M x M)', _checked=True) -> 'PP(M x M)':
        r"""Return the cross-intersection of ``clan1`` and ``clan2``.

        The :term:`cross-intersection` of two :term:`clan`\s is a clan that contains the result of
        intersecting every :term:`relation` from one clan with every relation from the other clan.

        :return: The :term:`binary extension` of :term:`intersection` from the :term:`algebra of
            relations` (which inherits it from the :term:`algebra of sets`) to the :term:`algebra of
            clans` applied to ``clan1`` and ``clan2``, or `Undef()` if ``clan1`` or ``clan2`` are
            not :term:`clan`\s.
        """
        if _checked:
            if not is_member(clan1):
                return _undef.make_or_raise_undef2(clan1)
            if not is_member(clan2):
                return _undef.make_or_raise_undef2(clan2)
        else:
            assert is_member_or_undef(clan1)
            assert is_member_or_undef(clan2)
            if clan1 is _undef.Undef() or clan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_extend(clan1, clan2, _functools.partial(
            _sets.intersect, _checked=False), _checked=False)
        if not result.is_empty:
            result.cache_clan(_mo.CacheStatus.IS)
            if clan1.cached_is_functional or clan2.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if clan1.cached_is_right_functional or clan2.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
        return result
Пример #4
0
def binary_extend(set1: 'P( M )',
                  set2: 'P( M )',
                  op,
                  _checked=True) -> 'P( M )':
    r"""Return the :term:`binary extension` of ``op`` from one :term:`algebra` to another algebra.

    For this extension, the elements of the extended algebra must be :term:`set`\s of the
    elements of the original algebra.

    :param set1: A :term:`set` with elements on which ``op`` operates.
    :param set2: A set with elements on which ``op`` operates.
    :param op: A :term:`binary operation` that operates on the elements of ``set1`` and ``set2``.
    :return: A set that consists of the defined results of ``op`` when executed on all combinations
        of the elements of ``set1`` and ``set2``, or `Undef()` if either set is not a
        :class:`~.Set`.
    """
    if _checked:
        if not _sets.is_member(set1):
            return _undef.make_or_raise_undef2(set1)
        if not _sets.is_member(set2):
            return _undef.make_or_raise_undef2(set2)
    else:
        assert _sets.is_member_or_undef(set1)
        assert _sets.is_member_or_undef(set2)
        if set1 is _undef.Undef() or set2 is _undef.Undef():
            return _undef.make_or_raise_undef(2)

    def _get_values(_set1, _set2):
        for e1 in _set1:
            for e2 in _set2:
                result = op(e1, e2)
                if result is not _undef.Undef():
                    yield result

    return _mo.Set(_get_values(set1, set2), direct_load=True)
Пример #5
0
    def lhs_cross_functional_union(lhs: 'PP( MxM )', rhs: 'PP( MxM )',
                                   _checked=True) -> 'PP(M x M)':
        """Return the :term:`lhs-cross-functional union` ('left join') of ``lhs`` and ``rhs``.

        This operation results in a :term:`clan` that contains every :term:`relation` of a
        :term:`cross-functional union`, but also contains all relations in ``lhs`` that
        are not already part of one of the resulting relations.

        :param lhs: All relations in this clan are guaranteed to be represented in the result.
        :return: The resulting clan or `Undef()` if ``lhs`` or ``rhs`` are not clans.
        """
        if _checked:
            if not is_member(lhs):
                return _undef.make_or_raise_undef2(lhs)
            if not is_member(rhs):
                return _undef.make_or_raise_undef2(rhs)
        else:
            assert is_member_or_undef(lhs)
            assert is_member_or_undef(rhs)
            if lhs is _undef.Undef() or rhs is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        cfu = cross_functional_union(lhs, rhs, _checked=False)
        lhs_rest = _mo.Set(
            lhs_elem for lhs_elem in lhs
            if cross_functional_union(_mo.Set(lhs_elem, direct_load=True), rhs).is_empty)
        result = _sets.union(cfu, lhs_rest, _checked=False)
        if not result.is_empty:
            result.cache_clan(_mo.CacheStatus.IS)
            if lhs.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if lhs.cached_is_not_right_functional or rhs.cached_is_not_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS_NOT)
            if not rhs.is_empty and not lhs_rest.is_empty:
                result.cache_regular(_mo.CacheStatus.IS_NOT)
        return result
Пример #6
0
    def compose(rel1: 'P(M x M)', rel2: 'P(M x M)', _checked=True) -> 'P(M x M)':
        r"""Return the composition of ``rel1`` with ``rel2``.

        :return: The :term:`binary extension` of :term:`composition` from the :term:`algebra of
            couplets` to the :term:`algebra of relations`, applied to the :term:`relation`\s
            ``rel1`` and ``rel2``, or `Undef()` if ``rel1`` or ``rel2`` are not relations.
        """
        if _checked:
            if not is_member(rel1):
                return _undef.make_or_raise_undef2(rel1)
            if not is_member(rel2):
                return _undef.make_or_raise_undef2(rel2)
        else:
            assert is_member_or_undef(rel1)
            assert is_member_or_undef(rel2)
            if rel1 is _undef.Undef() or rel2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_extend(rel1, rel2, _functools.partial(
            _couplets.compose, _checked=False), _checked=False)
        if not result.is_empty:
            result.cache_relation(_mo.CacheStatus.IS)
            if rel1.cached_is_absolute and rel2.cached_is_absolute:
                result.cache_absolute(_mo.CacheStatus.IS)
            if rel1.cached_is_functional and rel2.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if rel1.cached_is_right_functional and rel2.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
        return result
Пример #7
0
    def cross_right_functional_union(clan1: 'PP(M x M)', clan2: 'PP(M x M)',
                                     _checked=True) -> 'PP(M x M)':
        r"""Return the cross-right-functional union of ``clan1`` and ``clan2``.

        The :term:`cross-right-functional union` of two :term:`clan`\s is the :term:`cross-union`
        of these clans, but removing all resulting :term:`relation`\s that are not
        :term:`right-functional`.

        :return: The :term:`binary extension` of the :term:`right-functional union` from the
            :term:`algebra of relations` to the :term:`algebra of clans`, applied to ``clan1`` and
            ``clan2``, or `Undef()` if ``clan1`` or ``clan2`` are not :term:`clan`\s.
        """
        if _checked:
            if not is_member(clan1):
                return _undef.make_or_raise_undef2(clan1)
            if not is_member(clan2):
                return _undef.make_or_raise_undef2(clan2)
        else:
            assert is_member_or_undef(clan1)
            assert is_member_or_undef(clan2)
            if clan1 is _undef.Undef() or clan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_extend(clan1, clan2, _functools.partial(
            _relations.right_functional_union, _checked=False), _checked=False)
        if not result.is_empty:
            result.cache_clan(_mo.CacheStatus.IS)
            result.cache_right_functional(_mo.CacheStatus.IS)
            if clan1.cached_is_not_functional or clan2.cached_is_not_functional:
                result.cache_functional(_mo.CacheStatus.IS_NOT)
        return result
Пример #8
0
    def cross_intersect(multiclan1: 'P(P(M x M) x N)',
                        multiclan2: 'PP(M x M)',
                        _checked=True) -> 'PP(M x M)':
        r"""Return the :term:`cross-intersection` of ``multiclan1`` and ``multiclan2``.

        :return: The :term:`binary multi-extension` of :term:`intersection` from the :term:`algebra
            of relations` (which inherits it from the :term:`algebra of sets`) to the :term:`algebra
            of multiclans` applied to ``multiclan1`` and ``multiclan2``, or `Undef()` if
            ``multiclan1`` or ``multiclan2`` are not :term:`multiclan`\s.
        """
        if _checked:
            if not is_member(multiclan1):
                return _undef.make_or_raise_undef2(multiclan1)
            if not is_member(multiclan2):
                return _undef.make_or_raise_undef2(multiclan2)
        else:
            assert is_member_or_undef(multiclan1)
            assert is_member_or_undef(multiclan2)
            if multiclan1 is _undef.Undef() or multiclan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_multi_extend(multiclan1,
                                                multiclan2,
                                                _functools.partial(
                                                    _sets.intersect,
                                                    _checked=False),
                                                _checked=False)
        if not result.is_empty:
            result.cache_multiclan(_mo.CacheStatus.IS)
            if multiclan1.cached_is_functional or multiclan2.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if multiclan1.cached_is_right_functional or multiclan2.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
        return result
Пример #9
0
    def compose(multiclan1: 'P(P(M x M) x N)',
                multiclan2: 'P(P(M x M) x N)',
                _checked=True) -> 'P(P(M x M) x N)':
        r"""Return the composition of ``multiclan1`` with ``multiclan2``.

        :return: The :term:`binary multi-extension` of :term:`composition` from the
            :term:`algebra of relations` to the :term:`algebra of multiclans`, applied to
            ``multiclan1`` and ``multiclan2``, or `Undef()` if ``multiclan1`` or ``multiclan2``
            are not :term:`multiclan`\s.
        """
        if _checked:
            if not is_member(multiclan1):
                return _undef.make_or_raise_undef2(multiclan1)
            if not is_member(multiclan2):
                return _undef.make_or_raise_undef2(multiclan2)
        else:
            assert is_member_or_undef(multiclan1)
            assert is_member_or_undef(multiclan2)
            if multiclan1 is _undef.Undef() or multiclan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_multi_extend(multiclan1,
                                                multiclan2,
                                                _functools.partial(
                                                    _relations.compose,
                                                    _checked=False),
                                                _checked=False)
        if not result.is_empty:
            result.cache_multiclan(_mo.CacheStatus.IS)
            if multiclan1.cached_is_absolute and multiclan2.cached_is_absolute:
                result.cache_absolute(_mo.CacheStatus.IS)
            if multiclan1.cached_is_functional and multiclan2.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if multiclan1.cached_is_right_functional and multiclan2.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
        return result
Пример #10
0
def fill_lefts(rel: 'P(M x M)',
               renames: 'P(M x M)',
               _checked=True) -> 'P(M x M)':
    r"""Return the left components in ``rel`` that are missing in ``renames`` as a diagonal
    unioned with ``renames``.

    The purpose is to create a :term:`relation` that can be used with the :term:`composition`
    operation to change (rename) one or more :term:`left component`\s and leave the rest alone.

    :param rel: The :term:`relation` that provides the full :term:`left set`.
    :param renames: A relation where the :term:`right component`\s are meant to be
        :term:`composition` 'origins' and the :term:`left component`\s composition 'targets'.
    :return: A relation that contains all members of ``renames`` unioned with a :term:`diagonal`
        that consists of all left components in ``rel`` that are missing in ``renames``.
    """
    if _checked:
        if not is_member(rel):
            return _undef.make_or_raise_undef2(rel)
        if not is_member(renames):
            return _undef.make_or_raise_undef2(renames)
    else:
        assert is_member_or_undef(rel)
        assert is_member_or_undef(renames)
        if rel is _undef.Undef() or renames is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    missing_lefts = _sets.minus(get_lefts(rel, _checked=False),
                                get_rights(renames, _checked=False),
                                _checked=False)
    diag_missing_lefts = diag(*missing_lefts, _checked=False)
    result = _sets.union(renames, diag_missing_lefts, _checked=False)
    assert result.cached_is_relation
    return result
Пример #11
0
    def cross_right_functional_union(clan1: 'PP(M x M)',
                                     clan2: 'PP(M x M)',
                                     _checked=True) -> 'PP(M x M)':
        r"""Return the cross-right-functional union of ``clan1`` and ``clan2``.

        The :term:`cross-right-functional union` of two :term:`clan`\s is the :term:`cross-union`
        of these clans, but removing all resulting :term:`relation`\s that are not
        :term:`right-functional`.

        :return: The :term:`binary extension` of the :term:`right-functional union` from the
            :term:`algebra of relations` to the :term:`algebra of clans`, applied to ``clan1`` and
            ``clan2``, or `Undef()` if ``clan1`` or ``clan2`` are not :term:`clan`\s.
        """
        if _checked:
            if not is_member(clan1):
                return _undef.make_or_raise_undef2(clan1)
            if not is_member(clan2):
                return _undef.make_or_raise_undef2(clan2)
        else:
            assert is_member_or_undef(clan1)
            assert is_member_or_undef(clan2)
            if clan1 is _undef.Undef() or clan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_extend(
            clan1,
            clan2,
            _functools.partial(_relations.right_functional_union,
                               _checked=False),
            _checked=False)
        if not result.is_empty:
            result.cache_clan(_mo.CacheStatus.IS)
            result.cache_right_functional(_mo.CacheStatus.IS)
            if clan1.cached_is_not_functional or clan2.cached_is_not_functional:
                result.cache_functional(_mo.CacheStatus.IS_NOT)
        return result
Пример #12
0
    def cross_intersect(clan1: 'PP(M x M)',
                        clan2: 'PP(M x M)',
                        _checked=True) -> 'PP(M x M)':
        r"""Return the cross-intersection of ``clan1`` and ``clan2``.

        The :term:`cross-intersection` of two :term:`clan`\s is a clan that contains the result of
        intersecting every :term:`relation` from one clan with every relation from the other clan.

        :return: The :term:`binary extension` of :term:`intersection` from the :term:`algebra of
            relations` (which inherits it from the :term:`algebra of sets`) to the :term:`algebra of
            clans` applied to ``clan1`` and ``clan2``, or `Undef()` if ``clan1`` or ``clan2`` are
            not :term:`clan`\s.
        """
        if _checked:
            if not is_member(clan1):
                return _undef.make_or_raise_undef2(clan1)
            if not is_member(clan2):
                return _undef.make_or_raise_undef2(clan2)
        else:
            assert is_member_or_undef(clan1)
            assert is_member_or_undef(clan2)
            if clan1 is _undef.Undef() or clan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_extend(clan1,
                                          clan2,
                                          _functools.partial(_sets.intersect,
                                                             _checked=False),
                                          _checked=False)
        if not result.is_empty:
            result.cache_clan(_mo.CacheStatus.IS)
            if clan1.cached_is_functional or clan2.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if clan1.cached_is_right_functional or clan2.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
        return result
Пример #13
0
    def intersect(multiset1: 'P( M x N )',
                  multiset2: 'P( M x N )',
                  _checked=True) -> 'P( M x N )':
        """Return the multiset intersection of ``multiset1`` with ``multiset2``.

        :return: The :term:`multiset intersection` of ``multiset1`` and ``multiset2`` or `Undef()`
            if ``multiset1`` or ``multiset2`` are not instances of :class:`~.Multiset`.
        """
        if _checked:
            if not is_member(multiset1):
                return _undef.make_or_raise_undef2(multiset1)
            if not is_member(multiset2):
                return _undef.make_or_raise_undef2(multiset2)
        else:
            assert is_member_or_undef(multiset1)
            assert is_member_or_undef(multiset2)
            if multiset1 is _undef.Undef() or multiset2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        values = multiset1.data & multiset2.data
        result = _mo.Multiset(values)
        if not result.is_empty:
            # Multiclan flags:
            if multiset1.cached_is_multiclan or multiset2.cached_is_multiclan:
                result.cache_multiclan(CacheStatus.IS)
                if multiset1.cached_is_absolute or multiset2.cached_is_absolute:
                    result.cache_absolute(CacheStatus.IS)
                if multiset1.cached_is_functional or multiset2.cached_is_functional:
                    result.cache_functional(CacheStatus.IS)
                if multiset1.cached_is_right_functional or multiset2.cached_is_right_functional:
                    result.cache_right_functional(CacheStatus.IS)
                if multiset1.cached_is_regular or multiset2.cached_is_regular:
                    result.cache_regular(CacheStatus.IS)
                if multiset1.cached_is_right_regular or multiset2.cached_is_right_regular:
                    result.cache_right_regular(CacheStatus.IS)
        return result
Пример #14
0
    def compose(multiclan1: 'P(P(M x M) x N)', multiclan2: 'P(P(M x M) x N)',
                _checked=True) -> 'P(P(M x M) x N)':
        r"""Return the composition of ``multiclan1`` with ``multiclan2``.

        :return: The :term:`binary multi-extension` of :term:`composition` from the
            :term:`algebra of relations` to the :term:`algebra of multiclans`, applied to
            ``multiclan1`` and ``multiclan2``, or `Undef()` if ``multiclan1`` or ``multiclan2``
            are not :term:`multiclan`\s.
        """
        if _checked:
            if not is_member(multiclan1):
                return _undef.make_or_raise_undef2(multiclan1)
            if not is_member(multiclan2):
                return _undef.make_or_raise_undef2(multiclan2)
        else:
            assert is_member_or_undef(multiclan1)
            assert is_member_or_undef(multiclan2)
            if multiclan1 is _undef.Undef() or multiclan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_multi_extend(multiclan1, multiclan2, _functools.partial(
            _relations.compose, _checked=False), _checked=False)
        if not result.is_empty:
            result.cache_multiclan(_mo.CacheStatus.IS)
            if multiclan1.cached_is_absolute and multiclan2.cached_is_absolute:
                result.cache_absolute(_mo.CacheStatus.IS)
            if multiclan1.cached_is_functional and multiclan2.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if multiclan1.cached_is_right_functional and multiclan2.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
        return result
Пример #15
0
    def cross_intersect(multiclan1: 'P(P(M x M) x N)', multiclan2: 'PP(M x M)',
                        _checked=True) -> 'PP(M x M)':
        r"""Return the :term:`cross-intersection` of ``multiclan1`` and ``multiclan2``.

        :return: The :term:`binary multi-extension` of :term:`intersection` from the :term:`algebra
            of relations` (which inherits it from the :term:`algebra of sets`) to the :term:`algebra
            of multiclans` applied to ``multiclan1`` and ``multiclan2``, or `Undef()` if
            ``multiclan1`` or ``multiclan2`` are not :term:`multiclan`\s.
        """
        if _checked:
            if not is_member(multiclan1):
                return _undef.make_or_raise_undef2(multiclan1)
            if not is_member(multiclan2):
                return _undef.make_or_raise_undef2(multiclan2)
        else:
            assert is_member_or_undef(multiclan1)
            assert is_member_or_undef(multiclan2)
            if multiclan1 is _undef.Undef() or multiclan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_multi_extend(multiclan1, multiclan2, _functools.partial(
            _sets.intersect, _checked=False), _checked=False)
        if not result.is_empty:
            result.cache_multiclan(_mo.CacheStatus.IS)
            if multiclan1.cached_is_functional or multiclan2.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if multiclan1.cached_is_right_functional or multiclan2.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
        return result
Пример #16
0
    def intersect(multiset1: 'P( M x N )', multiset2: 'P( M x N )', _checked=True) -> 'P( M x N )':
        """Return the multiset intersection of ``multiset1`` with ``multiset2``.

        :return: The :term:`multiset intersection` of ``multiset1`` and ``multiset2`` or `Undef()`
            if ``multiset1`` or ``multiset2`` are not instances of :class:`~.Multiset`.
        """
        if _checked:
            if not is_member(multiset1):
                return _undef.make_or_raise_undef2(multiset1)
            if not is_member(multiset2):
                return _undef.make_or_raise_undef2(multiset2)
        else:
            assert is_member_or_undef(multiset1)
            assert is_member_or_undef(multiset2)
            if multiset1 is _undef.Undef() or multiset2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        values = multiset1.data & multiset2.data
        result = _mo.Multiset(values)
        if not result.is_empty:
            # Multiclan flags:
            if multiset1.cached_is_multiclan or multiset2.cached_is_multiclan:
                result.cache_multiclan(_mo.CacheStatus.IS)
                if multiset1.cached_is_absolute or multiset2.cached_is_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS)
                if multiset1.cached_is_functional or multiset2.cached_is_functional:
                    result.cache_functional(_mo.CacheStatus.IS)
                if multiset1.cached_is_right_functional or multiset2.cached_is_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS)
                if multiset1.cached_is_regular or multiset2.cached_is_regular:
                    result.cache_regular(_mo.CacheStatus.IS)
                if multiset1.cached_is_right_regular or multiset2.cached_is_right_regular:
                    result.cache_right_regular(_mo.CacheStatus.IS)
        return result
Пример #17
0
    def superstrict(multiset1: 'P( M x N )',
                    multiset2: 'P( M X N )',
                    _checked=True) -> 'P( M X N )':
        """Return ``multiset1`` if ``multiset1`` is a superset of ``multiset2`` or `Undef()` if not.

        :return: The :term:`superstriction` of ``multiset1`` and ``multiset2`` (may return
            `Undef()`). Also return `Undef()` if ``multiset1`` or ``multiset2`` are not instances
            of :class:`~.Multiset`.
        """
        if _checked:
            if not is_member(multiset1):
                return _undef.make_or_raise_undef2(multiset1)
            if not is_member(multiset2):
                return _undef.make_or_raise_undef2(multiset2)
        else:
            assert is_member_or_undef(multiset1)
            assert is_member_or_undef(multiset2)
            if multiset1 is _undef.Undef() or multiset2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        if not is_superset_of(multiset1, multiset2, _checked=False):
            return _undef.make_or_raise_undef(2)
        if not multiset1.is_empty:
            # Multiclan flags:
            if multiset1.cached_is_clan:
                if multiset2.cached_is_not_absolute:
                    multiset1.cache_absolute(CacheStatus.IS_NOT)
                if multiset2.cached_is_not_functional:
                    multiset1.cache_functional(CacheStatus.IS_NOT)
                if multiset2.cached_is_not_right_functional:
                    multiset1.cache_right_functional(CacheStatus.IS_NOT)
                if multiset2.cached_is_not_regular:
                    multiset1.cache_regular(CacheStatus.IS_NOT)
                if multiset2.cached_is_not_right_regular:
                    multiset1.cache_right_regular(CacheStatus.IS_NOT)
        return multiset1
Пример #18
0
def binary_extend(set1: 'P( M )', set2: 'P( M )', op, _checked=True) -> 'P( M )':
    r"""Return the :term:`binary extension` of ``op`` from one :term:`algebra` to another algebra.

    For this extension, the elements of the extended algebra must be :term:`set`\s of the
    elements of the original algebra.

    :param set1: A :term:`set` with elements on which ``op`` operates.
    :param set2: A set with elements on which ``op`` operates.
    :param op: A :term:`binary operation` that operates on the elements of ``set1`` and ``set2``.
    :return: A set that consists of the defined results of ``op`` when executed on all combinations
        of the elements of ``set1`` and ``set2``, or `Undef()` if either set is not a
        :class:`~.Set`.
    """
    if _checked:
        if not _sets.is_member(set1):
            return _undef.make_or_raise_undef2(set1)
        if not _sets.is_member(set2):
            return _undef.make_or_raise_undef2(set2)
    else:
        assert _sets.is_member_or_undef(set1)
        assert _sets.is_member_or_undef(set2)
        if set1 is _undef.Undef() or set2 is _undef.Undef():
            return _undef.make_or_raise_undef(2)

    def _get_values(_set1, _set2):
        for e1 in _set1:
            for e2 in _set2:
                result = op(e1, e2)
                if result is not _undef.Undef():
                    yield result

    return _mo.Set(_get_values(set1, set2), direct_load=True)
Пример #19
0
    def compose(rel1: 'P(M x M)',
                rel2: 'P(M x M)',
                _checked=True) -> 'P(M x M)':
        r"""Return the composition of ``rel1`` with ``rel2``.

        :return: The :term:`binary extension` of :term:`composition` from the :term:`algebra of
            couplets` to the :term:`algebra of relations`, applied to the :term:`relation`\s
            ``rel1`` and ``rel2``, or `Undef()` if ``rel1`` or ``rel2`` are not relations.
        """
        if _checked:
            if not is_member(rel1):
                return _undef.make_or_raise_undef2(rel1)
            if not is_member(rel2):
                return _undef.make_or_raise_undef2(rel2)
        else:
            assert is_member_or_undef(rel1)
            assert is_member_or_undef(rel2)
            if rel1 is _undef.Undef() or rel2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_extend(rel1,
                                          rel2,
                                          _functools.partial(_couplets.compose,
                                                             _checked=False),
                                          _checked=False)
        if not result.is_empty:
            result.cache_relation(_mo.CacheStatus.IS)
            if rel1.cached_is_absolute and rel2.cached_is_absolute:
                result.cache_absolute(_mo.CacheStatus.IS)
            if rel1.cached_is_functional and rel2.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if rel1.cached_is_right_functional and rel2.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
        return result
Пример #20
0
    def superstrict(multiset1: 'P( M x N )', multiset2: 'P( M X N )',
                    _checked=True) -> 'P( M X N )':
        """Return ``multiset1`` if ``multiset1`` is a superset of ``multiset2`` or `Undef()` if not.

        :return: The :term:`superstriction` of ``multiset1`` and ``multiset2`` (may return
            `Undef()`). Also return `Undef()` if ``multiset1`` or ``multiset2`` are not instances
            of :class:`~.Multiset`.
        """
        if _checked:
            if not is_member(multiset1):
                return _undef.make_or_raise_undef2(multiset1)
            if not is_member(multiset2):
                return _undef.make_or_raise_undef2(multiset2)
        else:
            assert is_member_or_undef(multiset1)
            assert is_member_or_undef(multiset2)
            if multiset1 is _undef.Undef() or multiset2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        if not is_superset_of(multiset1, multiset2, _checked=False):
            return _undef.make_or_raise_undef(2)
        if not multiset1.is_empty:
            # Multiclan flags:
            if multiset1.cached_is_clan:
                if multiset2.cached_is_not_absolute:
                    multiset1.cache_absolute(_mo.CacheStatus.IS_NOT)
                if multiset2.cached_is_not_functional:
                    multiset1.cache_functional(_mo.CacheStatus.IS_NOT)
                if multiset2.cached_is_not_right_functional:
                    multiset1.cache_right_functional(_mo.CacheStatus.IS_NOT)
                if multiset2.cached_is_not_regular:
                    multiset1.cache_regular(_mo.CacheStatus.IS_NOT)
                if multiset2.cached_is_not_right_regular:
                    multiset1.cache_right_regular(_mo.CacheStatus.IS_NOT)
        return multiset1
Пример #21
0
def fill_lefts(rel: 'P(M x M)', renames: 'P(M x M)', _checked=True) -> 'P(M x M)':
    r"""Return the left components in ``rel`` that are missing in ``renames`` as a diagonal
    unioned with ``renames``.

    The purpose is to create a :term:`relation` that can be used with the :term:`composition`
    operation to change (rename) one or more :term:`left component`\s and leave the rest alone.

    :param rel: The :term:`relation` that provides the full :term:`left set`.
    :param renames: A relation where the :term:`right component`\s are meant to be
        :term:`composition` 'origins' and the :term:`left component`\s composition 'targets'.
    :return: A relation that contains all members of ``renames`` unioned with a :term:`diagonal`
        that consists of all left components in ``rel`` that are missing in ``renames``.
    """
    if _checked:
        if not is_member(rel):
            return _undef.make_or_raise_undef2(rel)
        if not is_member(renames):
            return _undef.make_or_raise_undef2(renames)
    else:
        assert is_member_or_undef(rel)
        assert is_member_or_undef(renames)
        if rel is _undef.Undef() or renames is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    missing_lefts = _sets.minus(get_lefts(rel, _checked=False),
                                get_rights(renames, _checked=False), _checked=False)
    diag_missing_lefts = diag(*missing_lefts, _checked=False)
    result = _sets.union(renames, diag_missing_lefts, _checked=False)
    assert result.cached_is_relation
    return result
Пример #22
0
    def superstrict(multiclan1: 'P(P(M x M) x N)',
                    multiclan2: 'P(P(M x M) x N)',
                    _checked=True) -> 'P(P(M x M) x N)':
        r"""Return the superstriction of ``multiclan1`` and ``multiclan2``.

        The :term:`superstriction` of two :term:`multiclan`\s is a multiclan that contains all
        :term:`relation`\s from ``multiclan1`` that are a :term:`supermultiset` of a relation from
        ``multiclan2``.

        :return: The :term:`binary multi-extension` of :term:`superstriction` from the
            :term:`algebra of relations` (which inherits it from the :term:`algebra of sets`) to the
            :term:`algebra of multiclans` applied to ``multiclan1`` and ``multiclan2``, or `Undef()`
            if ``multiclan1`` or ``multiclan2`` are not :term:`multiclan`\s.
        """
        if _checked:
            if not is_member(multiclan1):
                return _undef.make_or_raise_undef2(multiclan1)
            if not is_member(multiclan2):
                return _undef.make_or_raise_undef2(multiclan2)
        else:
            assert is_member_or_undef(multiclan1)
            assert is_member_or_undef(multiclan2)
            if multiclan1 is _undef.Undef() or multiclan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_multi_extend(multiclan1,
                                                multiclan2,
                                                _functools.partial(
                                                    _sets.superstrict,
                                                    _checked=False),
                                                _checked=False)
        for elem, multi in result.data.items():
            result.data[elem] = multiclan2.data[elem]
        if not result.is_empty:
            result.cache_multiclan(_mo.CacheStatus.IS)
            if multiclan1.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if multiclan1.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
            if multiclan1.cached_is_reflexive:
                result.cache_reflexive(_mo.CacheStatus.IS)
            if multiclan1.cached_is_symmetric:
                result.cache_symmetric(_mo.CacheStatus.IS)
            if multiclan1.cached_is_transitive:
                result.cache_transitive(_mo.CacheStatus.IS)
            if multiclan1.cached_is_regular:
                result.cache_regular(_mo.CacheStatus.IS)
            if multiclan1.cached_is_right_regular:
                result.cache_right_regular(_mo.CacheStatus.IS)
        return result
Пример #23
0
    def minus(set1: 'P( M )', set2: 'P( M )', _checked=True) -> 'P( M )':
        r"""Return the set difference of ``set1`` and ``set2``.

        :return: The :term:`difference` of ``set1`` and ``set2`` or `Undef()` if ``set1`` or
            ``set2`` are not :term:`set`\s (that is, instances of :class:`~.Set`).
        """
        # pylint: disable=too-many-branches
        if _checked:
            if not is_member(set1):
                return _undef.make_or_raise_undef2(set1)
            if not is_member(set2):
                return _undef.make_or_raise_undef2(set2)
        else:
            assert is_member_or_undef(set1)
            assert is_member_or_undef(set2)
            if set1 is _undef.Undef() or set2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _mo.Set(set1.data.difference(set2.data), direct_load=True)
        if not result.is_empty:
            # Relation flags:
            if set1.cached_is_relation:
                result.cache_relation(_mo.CacheStatus.IS)
                if set1.cached_is_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS)
                if set1.cached_is_functional:
                    result.cache_functional(_mo.CacheStatus.IS)
                if set1.cached_is_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS)
            # Clan flags:
            if set1.cached_is_clan:
                result.cache_clan(_mo.CacheStatus.IS)
                if set1.cached_is_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS)
                if set1.cached_is_functional:
                    result.cache_functional(_mo.CacheStatus.IS)
                if set1.cached_is_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS)
                if set1.cached_is_reflexive:
                    result.cache_reflexive(_mo.CacheStatus.IS)
                if set1.cached_is_symmetric:
                    result.cache_symmetric(_mo.CacheStatus.IS)
                if set1.cached_is_transitive:
                    result.cache_transitive(_mo.CacheStatus.IS)
                if set1.cached_is_regular:
                    result.cache_regular(_mo.CacheStatus.IS)
                if set1.cached_is_right_regular:
                    result.cache_right_regular(_mo.CacheStatus.IS)
        return result
Пример #24
0
    def minus(set1: 'P( M )', set2: 'P( M )', _checked=True) -> 'P( M )':
        r"""Return the set difference of ``set1`` and ``set2``.

        :return: The :term:`difference` of ``set1`` and ``set2`` or `Undef()` if ``set1`` or
            ``set2`` are not :term:`set`\s (that is, instances of :class:`~.Set`).
        """
        # pylint: disable=too-many-branches
        if _checked:
            if not is_member(set1):
                return _undef.make_or_raise_undef2(set1)
            if not is_member(set2):
                return _undef.make_or_raise_undef2(set2)
        else:
            assert is_member_or_undef(set1)
            assert is_member_or_undef(set2)
            if set1 is _undef.Undef() or set2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _mo.Set(set1.data.difference(set2.data), direct_load=True)
        if not result.is_empty:
            # Relation flags:
            if set1.cached_is_relation:
                result.cache_relation(_mo.CacheStatus.IS)
                if set1.cached_is_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS)
                if set1.cached_is_functional:
                    result.cache_functional(_mo.CacheStatus.IS)
                if set1.cached_is_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS)
            # Clan flags:
            if set1.cached_is_clan:
                result.cache_clan(_mo.CacheStatus.IS)
                if set1.cached_is_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS)
                if set1.cached_is_functional:
                    result.cache_functional(_mo.CacheStatus.IS)
                if set1.cached_is_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS)
                if set1.cached_is_reflexive:
                    result.cache_reflexive(_mo.CacheStatus.IS)
                if set1.cached_is_symmetric:
                    result.cache_symmetric(_mo.CacheStatus.IS)
                if set1.cached_is_transitive:
                    result.cache_transitive(_mo.CacheStatus.IS)
                if set1.cached_is_regular:
                    result.cache_regular(_mo.CacheStatus.IS)
                if set1.cached_is_right_regular:
                    result.cache_right_regular(_mo.CacheStatus.IS)
        return result
Пример #25
0
    def transpose(rel: 'P(M x M)', _checked=True) -> 'P(M x M)':
        """Return a relation where all couplets have their left and right components swapped.

        :return: The :term:`unary extension` of :term:`transposition` from the
            :term:`algebra of couplets` to the :term:`algebra of relations`, applied to the
            :term:`relation` ``rel``, or `Undef()` if ``rel`` is not a relation.
        """
        if _checked:
            if not is_member(rel):
                return _undef.make_or_raise_undef2(rel)
        else:
            assert is_member_or_undef(rel)
            if rel is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.unary_extend(rel,
                                         _functools.partial(
                                             _couplets.transpose,
                                             _checked=False),
                                         _checked=False)
        if not result.is_empty:
            result.cache_relation(_mo.CacheStatus.IS)
            result.cache_absolute(rel.cached_absolute)
            result.cache_functional(rel.cached_right_functional)
            result.cache_right_functional(rel.cached_functional)
            result.cache_reflexive(rel.cached_reflexive)
            result.cache_symmetric(rel.cached_symmetric)
            result.cache_transitive(rel.cached_transitive)
        return result
Пример #26
0
def demultify(multiset: 'P( M x N )', _checked=True) -> 'P( M )':
    """Return a :term:`set` based on ``multiset`` that contains all elements without multiples."""
    if _checked:
        if not is_member(multiset):
            return _undef.make_or_raise_undef2(multiset)
    else:
        assert is_member_or_undef(multiset)
        if multiset is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    result = _mo.Set(multiset.data.keys(), direct_load=True)
    if not result.is_empty:
        result.cache_clan(multiset.cached_multiclan)
        if multiset.cached_is_multiclan:
            result.cache_absolute(multiset.cached_absolute)
            result.cache_functional(multiset.cached_functional)
            result.cache_right_functional(multiset.cached_right_functional)
            result.cache_reflexive(multiset.cached_reflexive)
            result.cache_symmetric(multiset.cached_symmetric)
            result.cache_transitive(multiset.cached_transitive)
            result.cache_regular(multiset.cached_regular)
            result.cache_right_regular(multiset.cached_right_regular)
        # We don't yet have a concept of multirelations (multisets of couplets). Because of this,
        # a multiset that is converted into a set may be a relation without us being able to know
        # this here. Because of this, the only flags we can propagate are multiclan flags.
    return result
Пример #27
0
def is_right_regular(mclan, _checked=True) -> bool:
    """Return whether ``mclan`` is right-regular.

    :return: ``True`` if ``mclan`` is :term:`right-regular`, ``False`` if not, or `Undef()` if
        ``mclan`` is not a :term:`multiclan`.
    """
    if _checked:
        if not is_member(mclan):
            return _undef.make_or_raise_undef2(mclan)
    else:
        assert is_member_or_undef(mclan)
        if mclan is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    if mclan.cached_right_regular == _mo.CacheStatus.UNKNOWN:
        # The empty set is already handled in Set().__init__ via flags initialization.
        if mclan.cached_is_not_right_functional:
            mclan.cache_right_regular(_mo.CacheStatus.IS_NOT)
            return False
        itr = iter(mclan.data)
        rel = next(itr)
        if not _relations.is_right_functional(rel):
            mclan.cache_right_regular(_mo.CacheStatus.IS_NOT)
            return False
        right_set = rel.get_right_set()
        right_regular = all(
            _relations.is_right_functional(rel) and right_set == rel.get_right_set() for rel in itr)
        mclan.cache_regular(_mo.CacheStatus.from_bool(right_regular))
    return mclan.cached_is_regular
Пример #28
0
def get_lefts(clan: 'PP(M x M)', _checked=True) -> 'P( M )':
    r"""Return the set of the left components of all couplets in all relations in ``clan``.

    :return: The :term:`union` of the :term:`left set`\s of all :term:`relation`\s in ``clan`` or
        `Undef()` if ``clan`` is not a :term:`clan`.
    """
    if _checked:
        if not is_member(clan):
            return _undef.make_or_raise_undef2(clan)
    else:
        assert is_member_or_undef(clan)
        if clan is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    if clan.is_empty:
        # The left set of an empty set is the empty set
        return clan
    clan_itr = iter(clan)
    left_set = _relations.get_lefts(next(clan_itr), _checked=False)
    for rel in clan_itr:
        left_set = _sets.union(_relations.get_lefts(rel, _checked=False),
                               left_set,
                               _checked=False)
    if not left_set.is_empty:
        if clan.cached_is_absolute:
            left_set.cache_absolute(CacheStatus.IS)
    return left_set
Пример #29
0
def demultify(multiset: 'P( M x N )', _checked=True) -> 'P( M )':
    """Return a :term:`set` based on ``multiset`` that contains all elements without multiples."""
    if _checked:
        if not is_member(multiset):
            return _undef.make_or_raise_undef2(multiset)
    else:
        assert is_member_or_undef(multiset)
        if multiset is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    result = _mo.Set(multiset.data.keys(), direct_load=True)
    if not result.is_empty:
        result.cache_clan(multiset.cached_multiclan)
        if multiset.cached_is_multiclan:
            result.cache_absolute(multiset.cached_absolute)
            result.cache_functional(multiset.cached_functional)
            result.cache_right_functional(multiset.cached_right_functional)
            result.cache_reflexive(multiset.cached_reflexive)
            result.cache_symmetric(multiset.cached_symmetric)
            result.cache_transitive(multiset.cached_transitive)
            result.cache_regular(multiset.cached_regular)
            result.cache_right_regular(multiset.cached_right_regular)
        # We don't yet have a concept of multirelations (multisets of couplets). Because of this,
        # a multiset that is converted into a set may be a relation without us being able to know
        # this here. Because of this, the only flags we can propagate are multiclan flags.
    return result
Пример #30
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
Пример #31
0
def big_intersect(set_: 'PP( M )', _checked=True) -> 'P( M )':
    """Return the intersection of all members of ``set_``.

    :return: The :term:`intersection` of all members of ``set_`` or `Undef()` if ``set_`` or any of
        its members are not instances of :class:`~.Set`.

    Example code:

    .. code::

        from algebraixlib.mathobjects import Set
        from algebraixlib.algebras.sets import big_intersect
        big_intersect(Set(Set('a', 'b'), Set('b', 'c')))
        # Output: Set(Atom('b'))
        big_intersect(Set(Set('a', 'b'), 'a'))
        # Output: <algebraixlib.undef.Undef at 0x4004978>
    """
    if _checked:
        if not is_member(set_):
            return _undef.make_or_raise_undef2(set_)
        for element in set_:
            if not is_member(element):
                return _undef.make_or_raise_undef(2)
    else:
        assert is_member_or_undef(set_)
        if set_ is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    return chain_binary_operation(
        set_, _functools.partial(intersect, _checked=False), is_member)
Пример #32
0
def chain_binary_operation(set_, binary_op, is_algebra_member):
    r"""Chain all elements of ``set_`` with the binary operation ``binary_op`` and return the
    result.

    :param set_: A :term:`set` of sets or :term:`multiset`\s.
    :param binary_op: The operation through which the members of ``set_`` are chained. It must be
        commutative and associative.
    :param is_algebra_member: The ``is_member()`` function of the :term:`algebra` of which the
        elements of ``set_`` must be members.
    :return: A member of ``algebra`` that is the result of chaining all elements of ``set_`` with
        the :term:`binary operation` ``binary_op``.
    """
    if not is_member(set_):
        return _undef.make_or_raise_undef2(set_)

    if set_.is_empty:
        return set_

    set_itr = iter(set_)
    element1 = next(set_itr)
    if not is_algebra_member(element1):
        return _undef.make_or_raise_undef()

    result = element1
    for element in set_itr:
        if not is_algebra_member(element):
            return _undef.make_or_raise_undef()
        result = binary_op(result, element)
    return result
Пример #33
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
Пример #34
0
def defined_at(mclan: 'P(P(M x M) x N)', left: '( M )', _checked=True):
    r"""Return the :term:`relation`\s of ``mclan`` that are defined for ``left``."""
    if not is_member(mclan):
        return _undef.make_or_raise_undef(2)
    if left is _undef.Undef():
        return _undef.make_or_raise_undef(2)
    result = _extension.unary_multi_extend(mclan,
                                           _functools.partial(
                                               _relations.defined_at,
                                               left=left,
                                               _checked=_checked),
                                           _checked=_checked)
    if result is _undef.Undef() or not result:
        return _undef.make_or_raise_undef2(result)
    result.cache_multiclan(_mo.CacheStatus.IS)
    if not result.is_empty:
        if mclan.cached_is_functional:
            result.cache_functional(_mo.CacheStatus.IS)
        if mclan.cached_is_right_functional:
            result.cache_right_functional(_mo.CacheStatus.IS)
        if mclan.cached_is_regular:
            result.cache_regular(_mo.CacheStatus.IS)
        if mclan.cached_is_right_regular:
            result.cache_right_regular(_mo.CacheStatus.IS)
    return result
Пример #35
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
Пример #36
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
Пример #37
0
    def transpose(rel: 'P(M x M)', _checked=True) -> 'P(M x M)':
        """Return a relation where all couplets have their left and right components swapped.

        :return: The :term:`unary extension` of :term:`transposition` from the
            :term:`algebra of couplets` to the :term:`algebra of relations`, applied to the
            :term:`relation` ``rel``, or `Undef()` if ``rel`` is not a relation.
        """
        if _checked:
            if not is_member(rel):
                return _undef.make_or_raise_undef2(rel)
        else:
            assert is_member_or_undef(rel)
            if rel is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.unary_extend(rel, _functools.partial(
            _couplets.transpose, _checked=False), _checked=False)
        if not result.is_empty:
            result.cache_relation(_mo.CacheStatus.IS)
            result.cache_absolute(rel.cached_absolute)
            result.cache_functional(rel.cached_right_functional)
            result.cache_right_functional(rel.cached_functional)
            result.cache_reflexive(rel.cached_reflexive)
            result.cache_symmetric(rel.cached_symmetric)
            result.cache_transitive(rel.cached_transitive)
        return result
Пример #38
0
def big_intersect(set_: 'PP( M )', _checked=True) -> 'P( M )':
    """Return the intersection of all members of ``set_``.

    :return: The :term:`intersection` of all members of ``set_`` or `Undef()` if ``set_`` or any of
        its members are not instances of :class:`~.Set`.

    Example code:

    .. code::

        from algebraixlib.mathobjects import Set
        from algebraixlib.algebras.sets import big_intersect
        big_intersect(Set(Set('a', 'b'), Set('b', 'c')))
        # Output: Set(Atom('b'))
        big_intersect(Set(Set('a', 'b'), 'a'))
        # Output: <algebraixlib.undef.Undef at 0x4004978>
    """
    if _checked:
        if not is_member(set_):
            return _undef.make_or_raise_undef2(set_)
        for element in set_:
            if not is_member(element):
                return _undef.make_or_raise_undef(2)
    else:
        assert is_member_or_undef(set_)
        if set_ is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    return chain_binary_operation(set_, _functools.partial(intersect, _checked=False), is_member)
Пример #39
0
def chain_binary_operation(set_, binary_op, is_algebra_member):
    r"""Chain all elements of ``set_`` with the binary operation ``binary_op`` and return the
    result.

    :param set_: A :term:`set` of sets or :term:`multiset`\s.
    :param binary_op: The operation through which the members of ``set_`` are chained. It must be
        commutative and associative.
    :param is_algebra_member: The ``is_member()`` function of the :term:`algebra` of which the
        elements of ``set_`` must be members.
    :return: A member of ``algebra`` that is the result of chaining all elements of ``set_`` with
        the :term:`binary operation` ``binary_op``.
    """
    if not is_member(set_):
        return _undef.make_or_raise_undef2(set_)

    if set_.is_empty:
        return set_

    set_itr = iter(set_)
    element1 = next(set_itr)
    if not is_algebra_member(element1):
        return _undef.make_or_raise_undef()

    result = element1
    for element in set_itr:
        if not is_algebra_member(element):
            return _undef.make_or_raise_undef()
        result = binary_op(result, element)
    return result
Пример #40
0
def is_right_regular(mclan, _checked=True) -> bool:
    """Return whether ``mclan`` is right-regular.

    :return: ``True`` if ``mclan`` is :term:`right-regular`, ``False`` if not, or `Undef()` if
        ``mclan`` is not a :term:`multiclan`.
    """
    if _checked:
        if not is_member(mclan):
            return _undef.make_or_raise_undef2(mclan)
    else:
        assert is_member_or_undef(mclan)
        if mclan is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    if mclan.cached_right_regular == _mo.CacheStatus.UNKNOWN:
        # The empty set is already handled in Set().__init__ via flags initialization.
        if mclan.cached_is_not_right_functional:
            mclan.cache_right_regular(_mo.CacheStatus.IS_NOT)
            return False
        itr = iter(mclan.data)
        rel = next(itr)
        if not _relations.is_right_functional(rel):
            mclan.cache_right_regular(_mo.CacheStatus.IS_NOT)
            return False
        right_set = rel.get_right_set()
        right_regular = all(
            _relations.is_right_functional(rel)
            and right_set == rel.get_right_set() for rel in itr)
        mclan.cache_regular(_mo.CacheStatus.from_bool(right_regular))
    return mclan.cached_is_regular
Пример #41
0
    def transpose(multiclan: 'P(P(M x M) x N)', _checked=True) -> 'P(P(M x M) x N)':
        """Return a multiclan where all relations have their left and right components swapped.

        :return: The :term:`unary multi-extension` of :term:`transposition` from the
            :term:`algebra of relations` to the :term:`algebra of multiclans`, applied to
            ``multiclan``, or `Undef()` if ``multiclan`` is not a :term:`multiclan`.
        """
        if _checked:
            if not is_member(multiclan):
                return _undef.make_or_raise_undef2(multiclan)
        else:
            assert is_member_or_undef(multiclan)
            if multiclan is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.unary_multi_extend(multiclan, _functools.partial(
            _relations.transpose, _checked=False), _checked=False)
        if not result.is_empty:
            result.cache_multiclan(_mo.CacheStatus.IS)
            result.cache_absolute(multiclan.cached_absolute)
            result.cache_functional(multiclan.cached_right_functional)
            result.cache_right_functional(multiclan.cached_functional)
            result.cache_reflexive(multiclan.cached_reflexive)
            result.cache_symmetric(multiclan.cached_symmetric)
            result.cache_transitive(multiclan.cached_transitive)
            result.cache_regular(multiclan.cached_right_regular)
            result.cache_right_regular(multiclan.cached_regular)
        return result
Пример #42
0
def get_rights(mclan: 'P(P(M x M) x N)', _checked=True) -> 'P( M )':
    r"""Return the set of the right components of all couplets in all relations in ``mclan``.

    :return: The :term:`union` of the :term:`right set`\s of all :term:`relation`\s in ``mclan`` or
        `Undef()` if ``mclan`` is not a :term:`multiclan`.
    """
    if _checked:
        if not is_member(mclan):
            return _undef.make_or_raise_undef2(mclan)
    else:
        assert is_member_or_undef(mclan)
        if mclan is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    if mclan.is_empty:
        # The right set of an empty set is the empty set
        return mclan
    clan_itr = iter(mclan)
    right_set = _relations.get_rights(next(clan_itr), _checked=False)
    for rel in clan_itr:
        right_set = _sets.union(_relations.get_rights(rel, _checked=False),
                                right_set,
                                _checked=False)
    if not right_set.is_empty:
        if mclan.cached_is_absolute:
            right_set.cache_absolute(_mo.CacheStatus.IS)
    return right_set
Пример #43
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
Пример #44
0
    def transpose(multiclan: 'P(P(M x M) x N)',
                  _checked=True) -> 'P(P(M x M) x N)':
        """Return a multiclan where all relations have their left and right components swapped.

        :return: The :term:`unary multi-extension` of :term:`transposition` from the
            :term:`algebra of relations` to the :term:`algebra of multiclans`, applied to
            ``multiclan``, or `Undef()` if ``multiclan`` is not a :term:`multiclan`.
        """
        if _checked:
            if not is_member(multiclan):
                return _undef.make_or_raise_undef2(multiclan)
        else:
            assert is_member_or_undef(multiclan)
            if multiclan is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.unary_multi_extend(multiclan,
                                               _functools.partial(
                                                   _relations.transpose,
                                                   _checked=False),
                                               _checked=False)
        if not result.is_empty:
            result.cache_multiclan(_mo.CacheStatus.IS)
            result.cache_absolute(multiclan.cached_absolute)
            result.cache_functional(multiclan.cached_right_functional)
            result.cache_right_functional(multiclan.cached_functional)
            result.cache_reflexive(multiclan.cached_reflexive)
            result.cache_symmetric(multiclan.cached_symmetric)
            result.cache_transitive(multiclan.cached_transitive)
            result.cache_regular(multiclan.cached_right_regular)
            result.cache_right_regular(multiclan.cached_regular)
        return result
Пример #45
0
def get_rights(mclan: 'P(P(M x M) x N)', _checked=True) -> 'P( M )':
    r"""Return the set of the right components of all couplets in all relations in ``mclan``.

    :return: The :term:`union` of the :term:`right set`\s of all :term:`relation`\s in ``mclan`` or
        `Undef()` if ``mclan`` is not a :term:`multiclan`.
    """
    if _checked:
        if not is_member(mclan):
            return _undef.make_or_raise_undef2(mclan)
    else:
        assert is_member_or_undef(mclan)
        if mclan is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    if mclan.is_empty:
        # The right set of an empty set is the empty set
        return mclan
    clan_itr = iter(mclan)
    right_set = _relations.get_rights(next(clan_itr), _checked=False)
    for rel in clan_itr:
        right_set = _sets.union(
            _relations.get_rights(rel, _checked=False), right_set, _checked=False)
    if not right_set.is_empty:
        if mclan.cached_is_absolute:
            right_set.cache_absolute(_mo.CacheStatus.IS)
    return right_set
Пример #46
0
def _to_listgen_check_args(mclan: 'P(P(M x M) x N)', offset: '( A )', limit: '( A )',
        _checked: bool=True) -> ():
    """Check the arguments of `multiclan_to_listgen` and `order_slice_to_listgen`. Return a tuple
    with the clean values of ``offset`` and ``limit`` or `Undef()` if there was a problem.
    """
    if _checked:
        if not is_member(mclan):
            return _undef.make_or_raise_undef2(mclan)
        if isinstance(offset, _mo.Atom) and isinstance(offset.value, int):
            pass
        elif isinstance(offset, int):
            offset = _mo.Atom(limit)
        elif offset is _undef.Undef():
            return _undef.make_or_raise_undef(2)
        else:
            return _undef.make_or_raise_undef()
        if isinstance(limit, _mo.Atom) \
                and (isinstance(limit.value, int) or limit.value == float('inf')):
            pass
        elif isinstance(limit, int) or limit == float('inf'):
            limit = _mo.Atom(limit)
        elif limit is _undef.Undef():
            return _undef.make_or_raise_undef(2)
        else:
            return _undef.make_or_raise_undef()
    else:
        if mclan is _undef.Undef() or offset is _undef.Undef() or limit is _undef.Undef():
            return _undef.make_or_raise_undef(2)
        assert is_member(mclan)
        assert offset.is_atom and isinstance(offset.value, int)
        assert limit.is_atom and (isinstance(limit.value, int) or limit.value == float('inf'))
    return offset, limit
Пример #47
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
Пример #48
0
    def union(multiset1: 'P( M x N )',
              multiset2: 'P( M x N )',
              _checked=True) -> 'P( M x N )':
        """Return the multiset union of ``multiset1`` with ``multiset2``.

        :return: The :term:`multiset union` of ``multiset1`` and ``multiset2`` or `Undef()` if
            ``multiset1`` or ``multiset2`` are not instances of :class:`~.Multiset`.
        """
        # pylint: disable=too-many-branches
        if _checked:
            if not is_member(multiset1):
                return _undef.make_or_raise_undef2(multiset1)
            if not is_member(multiset2):
                return _undef.make_or_raise_undef2(multiset2)
        else:
            assert is_member_or_undef(multiset1)
            assert is_member_or_undef(multiset2)
            if multiset1 is _undef.Undef() or multiset2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        values = multiset1.data | multiset2.data
        result = _mo.Multiset(values, direct_load=True)
        if not result.is_empty:
            # Multiclan flags:
            if multiset1.cached_is_multiclan and multiset2.cached_is_multiclan:
                result.cache_multiclan(CacheStatus.IS)
                if multiset1.cached_is_absolute and multiset2.cached_is_absolute:
                    result.cache_absolute(CacheStatus.IS)
                elif multiset1.cached_is_not_absolute or multiset2.cached_is_not_absolute:
                    result.cache_absolute(CacheStatus.IS_NOT)
                if multiset1.cached_is_functional and multiset2.cached_is_functional:
                    result.cache_functional(CacheStatus.IS)
                elif multiset1.cached_is_not_functional or multiset2.cached_is_not_functional:
                    result.cache_functional(CacheStatus.IS_NOT)
                if multiset1.cached_is_right_functional and multiset2.cached_is_right_functional:
                    result.cache_right_functional(CacheStatus.IS)
                elif multiset1.cached_is_not_right_functional \
                        or multiset2.cached_is_not_right_functional:
                    result.cache_right_functional(CacheStatus.IS_NOT)
                if multiset1.cached_is_not_regular or multiset1.cached_is_not_regular:
                    result.cache_regular(CacheStatus.IS_NOT)
                if multiset1.cached_is_not_right_regular or multiset1.cached_is_not_right_regular:
                    result.cache_right_regular(CacheStatus.IS_NOT)
            elif multiset1.cached_is_not_multiclan or multiset2.cached_is_not_multiclan:
                result.cache_multiclan(CacheStatus.IS_NOT)
        return result
Пример #49
0
    def is_superset_of(set1: 'P( M )', set2: 'P( M )', _checked=True) -> bool:
        r"""Return whether ``set1`` is a superset of ``set2``.

        :return: ``True`` if ``set1`` is a :term:`superset` of ``set2``, ``False`` if not. Return
            `Undef()` if ``set1`` or ``set2`` are not :term:`set`\s (that is, instances of
            :class:`~.Set`).
        """
        if _checked:
            if not is_member(set1):
                return _undef.make_or_raise_undef2(set1)
            if not is_member(set2):
                return _undef.make_or_raise_undef2(set2)
        else:
            assert is_member_or_undef(set1)
            assert is_member_or_undef(set2)
            if set1 is _undef.Undef() or set2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        return set1.data.issuperset(set2.data)
Пример #50
0
    def is_superset_of(set1: 'P( M )', set2: 'P( M )', _checked=True) -> bool:
        r"""Return whether ``set1`` is a superset of ``set2``.

        :return: ``True`` if ``set1`` is a :term:`superset` of ``set2``, ``False`` if not. Return
            `Undef()` if ``set1`` or ``set2`` are not :term:`set`\s (that is, instances of
            :class:`~.Set`).
        """
        if _checked:
            if not is_member(set1):
                return _undef.make_or_raise_undef2(set1)
            if not is_member(set2):
                return _undef.make_or_raise_undef2(set2)
        else:
            assert is_member_or_undef(set1)
            assert is_member_or_undef(set2)
            if set1 is _undef.Undef() or set2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        return set1.data.issuperset(set2.data)
Пример #51
0
    def superstrict(multiclan1: 'P(P(M x M) x N)', multiclan2: 'P(P(M x M) x N)',
                    _checked=True) -> 'P(P(M x M) x N)':
        r"""Return the superstriction of ``multiclan1`` and ``multiclan2``.

        The :term:`superstriction` of two :term:`multiclan`\s is a multiclan that contains all
        :term:`relation`\s from ``multiclan1`` that are a :term:`supermultiset` of a relation from
        ``multiclan2``.

        :return: The :term:`binary multi-extension` of :term:`superstriction` from the
            :term:`algebra of relations` (which inherits it from the :term:`algebra of sets`) to the
            :term:`algebra of multiclans` applied to ``multiclan1`` and ``multiclan2``, or `Undef()`
            if ``multiclan1`` or ``multiclan2`` are not :term:`multiclan`\s.
        """
        if _checked:
            if not is_member(multiclan1):
                return _undef.make_or_raise_undef2(multiclan1)
            if not is_member(multiclan2):
                return _undef.make_or_raise_undef2(multiclan2)
        else:
            assert is_member_or_undef(multiclan1)
            assert is_member_or_undef(multiclan2)
            if multiclan1 is _undef.Undef() or multiclan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_multi_extend(multiclan1, multiclan2, _functools.partial(
            _sets.superstrict, _checked=False), _checked=False)
        for elem, multi in result.data.items():
            result.data[elem] = multiclan2.data[elem]
        if not result.is_empty:
            result.cache_multiclan(_mo.CacheStatus.IS)
            if multiclan1.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if multiclan1.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
            if multiclan1.cached_is_reflexive:
                result.cache_reflexive(_mo.CacheStatus.IS)
            if multiclan1.cached_is_symmetric:
                result.cache_symmetric(_mo.CacheStatus.IS)
            if multiclan1.cached_is_transitive:
                result.cache_transitive(_mo.CacheStatus.IS)
            if multiclan1.cached_is_regular:
                result.cache_regular(_mo.CacheStatus.IS)
            if multiclan1.cached_is_right_regular:
                result.cache_right_regular(_mo.CacheStatus.IS)
        return result
Пример #52
0
    def superstrict(clan1: 'PP(M x M)',
                    clan2: 'PP(M x M)',
                    _checked=True) -> 'PP(M x M)':
        r"""Return the superstriction of ``clan1`` and ``clan2``.

        The :term:`superstriction` of two :term:`clan`\s is a clan that contains all
        :term:`relation`\s from ``clan1`` that are a :term:`superset` of a relation from ``clan2``.

        :return: The :term:`binary extension` of :term:`superstriction` from the :term:`algebra of
            sets` to the :term:`algebra of clans` applied to ``clan1`` and ``clan2``, or `Undef()`
            if ``clan1`` or ``clan2`` are not clans.
        """
        if _checked:
            if not is_member(clan1):
                return _undef.make_or_raise_undef2(clan1)
            if not is_member(clan2):
                return _undef.make_or_raise_undef2(clan2)
        else:
            assert is_member_or_undef(clan1)
            assert is_member_or_undef(clan2)
            if clan1 is _undef.Undef() or clan2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        result = _extension.binary_extend(clan1,
                                          clan2,
                                          _functools.partial(_sets.superstrict,
                                                             _checked=False),
                                          _checked=False)
        if not result.is_empty:
            result.cache_clan(_mo.CacheStatus.IS)
            if clan1.cached_is_functional:
                result.cache_functional(_mo.CacheStatus.IS)
            if clan1.cached_is_right_functional:
                result.cache_right_functional(_mo.CacheStatus.IS)
            if clan1.cached_is_reflexive:
                result.cache_reflexive(_mo.CacheStatus.IS)
            if clan1.cached_is_symmetric:
                result.cache_symmetric(_mo.CacheStatus.IS)
            if clan1.cached_is_transitive:
                result.cache_transitive(_mo.CacheStatus.IS)
            if clan1.cached_is_regular:
                result.cache_regular(_mo.CacheStatus.IS)
            if clan1.cached_is_right_regular:
                result.cache_right_regular(_mo.CacheStatus.IS)
        return result
Пример #53
0
def big_intersect(set_of_multisets: 'PP( M x N )', _checked=True) -> 'P( M x N )':
    """Return the multiset intersection of all members of ``multiset``.

    :return: The :term:`multiset intersection` of all members of ``set_of_multisets`` or `Undef()`
        if ``set_of_multisets`` is not a :class:`~.Set` or any of its members are not instances of
        :class:`~.Multiset`.
    """
    if _checked:
        if not isinstance(set_of_multisets, _mo.Set):
            return _undef.make_or_raise_undef2(set_of_multisets)
        for element in set_of_multisets:
            if not is_member(element):
                return _undef.make_or_raise_undef2(element)
    else:
        assert _sets.is_member_or_undef(set_of_multisets)
        if set_of_multisets is _undef.Undef():
            return _undef.make_or_raise_undef(2)
    return _sets.chain_binary_operation(
        set_of_multisets, _functools.partial(intersect, _checked=False), is_member)
Пример #54
0
    def union(multiset1: 'P( M x N )', multiset2: 'P( M x N )', _checked=True) -> 'P( M x N )':
        """Return the multiset union of ``multiset1`` with ``multiset2``.

        :return: The :term:`multiset union` of ``multiset1`` and ``multiset2`` or `Undef()` if
            ``multiset1`` or ``multiset2`` are not instances of :class:`~.Multiset`.
        """
        # pylint: disable=too-many-branches
        if _checked:
            if not is_member(multiset1):
                return _undef.make_or_raise_undef2(multiset1)
            if not is_member(multiset2):
                return _undef.make_or_raise_undef2(multiset2)
        else:
            assert is_member_or_undef(multiset1)
            assert is_member_or_undef(multiset2)
            if multiset1 is _undef.Undef() or multiset2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        values = multiset1.data | multiset2.data
        result = _mo.Multiset(values, direct_load=True)
        if not result.is_empty:
            # Multiclan flags:
            if multiset1.cached_is_multiclan and multiset2.cached_is_multiclan:
                result.cache_multiclan(_mo.CacheStatus.IS)
                if multiset1.cached_is_absolute and multiset2.cached_is_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS)
                elif multiset1.cached_is_not_absolute or multiset2.cached_is_not_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS_NOT)
                if multiset1.cached_is_functional and multiset2.cached_is_functional:
                    result.cache_functional(_mo.CacheStatus.IS)
                elif multiset1.cached_is_not_functional or multiset2.cached_is_not_functional:
                    result.cache_functional(_mo.CacheStatus.IS_NOT)
                if multiset1.cached_is_right_functional and multiset2.cached_is_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS)
                elif multiset1.cached_is_not_right_functional \
                        or multiset2.cached_is_not_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS_NOT)
                if multiset1.cached_is_not_regular or multiset1.cached_is_not_regular:
                    result.cache_regular(_mo.CacheStatus.IS_NOT)
                if multiset1.cached_is_not_right_regular or multiset1.cached_is_not_right_regular:
                    result.cache_right_regular(_mo.CacheStatus.IS_NOT)
            elif multiset1.cached_is_not_multiclan or multiset2.cached_is_not_multiclan:
                result.cache_multiclan(_mo.CacheStatus.IS_NOT)
        return result
Пример #55
0
    def superstrict(set1: 'P( M )', set2: 'P( M )', _checked=True) -> 'P( M )':
        r"""Return ``set1`` if it is a superset of ``set2``, otherwise return `Undef()`.

        :return: Return the :term:`superstriction` of ``set1`` and ``set1``; that is, return
            ``set1`` if it is a :term:`superset` of ``set2`` or `Undef()` if not. Also return
            `Undef()` if ``set1`` or ``set2`` are not :term:`set`\s (that is, instances of
            :class:`~.Set`).
        """
        # pylint: disable=too-many-branches
        if _checked:
            if not is_member(set1):
                return _undef.make_or_raise_undef2(set1)
            if not is_member(set2):
                return _undef.make_or_raise_undef2(set2)
        else:
            assert is_member_or_undef(set1)
            assert is_member_or_undef(set2)
            if set1 is _undef.Undef() or set2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        if not is_superset_of(set1, set2, _checked=False):
            return _undef.make_or_raise_undef(2)
        if not set1.is_empty:
            # Relation flags:
            if set1.cached_is_relation:
                if set2.cached_is_not_absolute:
                    set1.cache_absolute(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_functional:
                    set1.cache_functional(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_right_functional:
                    set1.cache_right_functional(_mo.CacheStatus.IS_NOT)
            # Clan flags:
            if set1.cached_is_clan:
                if set2.cached_is_not_absolute:
                    set1.cache_absolute(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_functional:
                    set1.cache_functional(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_right_functional:
                    set1.cache_right_functional(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_regular:
                    set1.cache_regular(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_right_regular:
                    set1.cache_right_regular(_mo.CacheStatus.IS_NOT)
        return set1
Пример #56
0
    def intersect(set1: 'P( M )', set2: 'P( M )', _checked=True) -> 'P( M )':
        r"""Return the intersection of ``set1`` with ``set2``.

        :return: The :term:`binary intersection` of ``set1`` and ``set2`` or `Undef()` if ``set1``
            or ``set2`` are not :term:`set`\s (that is, instances of :class:`~.Set`).
        """
        # pylint: disable=too-many-branches
        if _checked:
            if not is_member(set1):
                return _undef.make_or_raise_undef2(set1)
            if not is_member(set2):
                return _undef.make_or_raise_undef2(set2)
        else:
            assert is_member_or_undef(set1)
            assert is_member_or_undef(set2)
            if set1 is _undef.Undef() or set2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        values = set1.data.intersection(set2.data)
        result = _mo.Set(values, direct_load=True)
        if not result.is_empty:
            # Relation flags:
            if set1.cached_is_relation or set2.cached_is_relation:
                result.cache_relation(_mo.CacheStatus.IS)
                if set1.cached_is_absolute or set2.cached_is_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS)
                if set1.cached_is_functional or set2.cached_is_functional:
                    result.cache_functional(_mo.CacheStatus.IS)
                if set1.cached_is_right_functional or set2.cached_is_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS)
            # Clan flags:
            if set1.cached_is_clan or set2.cached_is_clan:
                result.cache_clan(_mo.CacheStatus.IS)
                if set1.cached_is_absolute or set2.cached_is_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS)
                if set1.cached_is_functional or set2.cached_is_functional:
                    result.cache_functional(_mo.CacheStatus.IS)
                if set1.cached_is_right_functional or set2.cached_is_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS)
                if set1.cached_is_regular or set2.cached_is_regular:
                    result.cache_regular(_mo.CacheStatus.IS)
                if set1.cached_is_right_regular or set2.cached_is_right_regular:
                    result.cache_right_regular(_mo.CacheStatus.IS)
        return result
Пример #57
0
    def intersect(set1: 'P( M )', set2: 'P( M )', _checked=True) -> 'P( M )':
        r"""Return the intersection of ``set1`` with ``set2``.

        :return: The :term:`binary intersection` of ``set1`` and ``set2`` or `Undef()` if ``set1``
            or ``set2`` are not :term:`set`\s (that is, instances of :class:`~.Set`).
        """
        # pylint: disable=too-many-branches
        if _checked:
            if not is_member(set1):
                return _undef.make_or_raise_undef2(set1)
            if not is_member(set2):
                return _undef.make_or_raise_undef2(set2)
        else:
            assert is_member_or_undef(set1)
            assert is_member_or_undef(set2)
            if set1 is _undef.Undef() or set2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        values = set1.data.intersection(set2.data)
        result = _mo.Set(values, direct_load=True)
        if not result.is_empty:
            # Relation flags:
            if set1.cached_is_relation or set2.cached_is_relation:
                result.cache_relation(_mo.CacheStatus.IS)
                if set1.cached_is_absolute or set2.cached_is_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS)
                if set1.cached_is_functional or set2.cached_is_functional:
                    result.cache_functional(_mo.CacheStatus.IS)
                if set1.cached_is_right_functional or set2.cached_is_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS)
            # Clan flags:
            if set1.cached_is_clan or set2.cached_is_clan:
                result.cache_clan(_mo.CacheStatus.IS)
                if set1.cached_is_absolute or set2.cached_is_absolute:
                    result.cache_absolute(_mo.CacheStatus.IS)
                if set1.cached_is_functional or set2.cached_is_functional:
                    result.cache_functional(_mo.CacheStatus.IS)
                if set1.cached_is_right_functional or set2.cached_is_right_functional:
                    result.cache_right_functional(_mo.CacheStatus.IS)
                if set1.cached_is_regular or set2.cached_is_regular:
                    result.cache_regular(_mo.CacheStatus.IS)
                if set1.cached_is_right_regular or set2.cached_is_right_regular:
                    result.cache_right_regular(_mo.CacheStatus.IS)
        return result
Пример #58
0
    def superstrict(set1: 'P( M )', set2: 'P( M )', _checked=True) -> 'P( M )':
        r"""Return ``set1`` if it is a superset of ``set2``, otherwise return `Undef()`.

        :return: Return the :term:`superstriction` of ``set1`` and ``set1``; that is, return
            ``set1`` if it is a :term:`superset` of ``set2`` or `Undef()` if not. Also return
            `Undef()` if ``set1`` or ``set2`` are not :term:`set`\s (that is, instances of
            :class:`~.Set`).
        """
        # pylint: disable=too-many-branches
        if _checked:
            if not is_member(set1):
                return _undef.make_or_raise_undef2(set1)
            if not is_member(set2):
                return _undef.make_or_raise_undef2(set2)
        else:
            assert is_member_or_undef(set1)
            assert is_member_or_undef(set2)
            if set1 is _undef.Undef() or set2 is _undef.Undef():
                return _undef.make_or_raise_undef(2)
        if not is_superset_of(set1, set2, _checked=False):
            return _undef.make_or_raise_undef(2)
        if not set1.is_empty:
            # Relation flags:
            if set1.cached_is_relation:
                if set2.cached_is_not_absolute:
                    set1.cache_absolute(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_functional:
                    set1.cache_functional(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_right_functional:
                    set1.cache_right_functional(_mo.CacheStatus.IS_NOT)
            # Clan flags:
            if set1.cached_is_clan:
                if set2.cached_is_not_absolute:
                    set1.cache_absolute(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_functional:
                    set1.cache_functional(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_right_functional:
                    set1.cache_right_functional(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_regular:
                    set1.cache_regular(_mo.CacheStatus.IS_NOT)
                if set2.cached_is_not_right_regular:
                    set1.cache_right_regular(_mo.CacheStatus.IS_NOT)
        return set1
Пример #59
0
def single(set_: _mo.Set):
    """Return the single element of ``set_``.

    :return: Return the single element of ``set_``, or `Undef()` if ``set_`` has not exactly one
        element or is not a :term:`set` (that is, an instance of :class:`~.Set`).
    """
    if not is_member(set_):
        return _undef.make_or_raise_undef2(set_)
    if set_.cardinality == 1:
        return next(iter(set_))
    return _undef.make_or_raise_undef(2)
Пример #60
0
def functional_add(func: 'P(M x M)', element: 'M x M') -> 'P(M x M)':
    """Add ``element`` to ``func`` and return the new functional relation.

    :param func: The source data. Must be a :term:`function`. It must not contain a :term:`couplet`
        with the same :term:`left component` as ``element``.
    :param element: The element to be added to ``func``. Must be a :class:`~.Couplet` and its
        :term:`left component` must not be a left component in ``func``.
    :return: The new relation, composed of ``func`` and ``element``.
    """
    if not is_member(func) or not is_functional(func):
        return _undef.make_or_raise_undef2(func)
    if not _couplets.is_member(element):
        return _undef.make_or_raise_undef2(element)
    if _sets.is_subset_of(_mo.Set(element.left), get_lefts(func)):
        return _undef.make_or_raise_undef(2)
    element_func = _mo.Set(element).cache_relation(_mo.CacheStatus.IS)
    result = _sets.union(func, element_func)
    assert result.cached_is_relation and is_functional(result)
    result.cache_functional(_mo.CacheStatus.IS)
    return result