def is_absolute_member(obj: _mo.MathObject) -> bool: """Return whether ``obj`` is a member of the :term:`absolute ground set` of this algebra. :return: ``True`` if ``obj`` is an :term:`absolute set`, ``False`` if not. """ if not obj.is_set: # If known to not be a set, it's also not an absolute set. No further checking or caching. return False # From this point on, `obj` is known to be a set. if obj.cached_absolute == _mo.CacheStatus.UNKNOWN: import algebraixlib.algebras.clans as _clans import algebraixlib.algebras.relations as _relations # In order to find out whether this is an absolute set, we need to know whether `obj` is a # relation or a clan (both sets). If it is one of these, it is not an absolute set -- but # we also don't know whether it is an absolute relation or clan. So we return `False` but # don't cache anything. (But we have now cached that it is a relation or a clan.) if _relations.is_member(obj) or _clans.is_member(obj): return False is_absolute_set = all(elem.is_atom for elem in obj) obj.cache_absolute(_mo.CacheStatus.from_bool(is_absolute_set)) # In order to determine whether this is an absolute set, we need to also examine whether this # is a relation or a clan (both are sets). Absolute relations and absolute clans are not # absolute sets. return obj.cached_is_absolute and not obj.cached_is_relation and not obj.cached_is_clan
def is_absolute_member(obj: _mo.MathObject) -> bool: """Return whether ``obj`` is a member of the :term:`absolute ground set` of this algebra. :type obj: _mo.MathObject|_mo.Multiset :return: ``True`` if ``obj`` is an :term:`absolute multiset`, ``False`` if not. """ import algebraixlib.algebras.multiclans as _multiclans if not obj.is_multiset: # If known to not be a multiset, it's also not an absolute multiset. No further checking or # caching. return False # From this point on, `obj` is known to be a multiset. if obj.cached_absolute == CacheStatus.UNKNOWN: # In order to find out whether this is an absolute multiset, we need to know whether `obj` # is a multiclan (also a multiset). If it is one, it is not an absolute multiset -- but # we also don't know whether it is an absolute multiclan. So we return `False` but don't # cache anything. (But we have now cached that it is a multiclan.) if _multiclans.is_member(obj): return False is_absolute_multiset = all(elem.is_atom for elem in obj.data) obj.cache_absolute(CacheStatus.from_bool(is_absolute_multiset)) # In order to determine whether this is an absolute multiset, we need to also examine whether # this is a multiclan (also a multisets). Absolute multiclans are not absolute multisets. return obj.cached_is_absolute and not obj.cached_is_multiclan
def is_absolute_member(obj: _mo.MathObject) -> bool: """Return whether ``obj`` is a member of the :term:`absolute ground set` of this algebra. :type obj: _mo.MathObject|_mo.Multiset :return: ``True`` if ``obj`` is an :term:`absolute multiset`, ``False`` if not. """ import algebraixlib.algebras.multiclans as _multiclans if not obj.is_multiset: # If known to not be a multiset, it's also not an absolute multiset. No further checking or # caching. return False # From this point on, `obj` is known to be a multiset. if obj.cached_absolute == _mo.CacheStatus.UNKNOWN: # In order to find out whether this is an absolute multiset, we need to know whether `obj` # is a multiclan (also a multiset). If it is one, it is not an absolute multiset -- but # we also don't know whether it is an absolute multiclan. So we return `False` but don't # cache anything. (But we have now cached that it is a multiclan.) if _multiclans.is_member(obj): return False is_absolute_multiset = all(elem.is_atom for elem in obj.data) obj.cache_absolute(_mo.CacheStatus.from_bool(is_absolute_multiset)) # In order to determine whether this is an absolute multiset, we need to also examine whether # this is a multiclan (also a multisets). Absolute multiclans are not absolute multisets. return obj.cached_is_absolute and not obj.cached_is_multiclan
def is_absolute_member(obj: _mo.MathObject) -> bool: """Return whether ``obj`` is a member of the :term:`absolute ground set` of this algebra. :return: ``True`` if ``obj`` is an :term:`absolute clan`, ``False`` if not. .. note:: This function may call :meth:`~.MathObject.get_ground_set` on ``obj``. The result of this operation is cached. """ if obj.cached_is_not_multiclan: # If known to not be a multiclan, it's also not an absolute multiclan. No further caching. return False # The `or` clause in this `if` statement is a safety thing. It should never hit. if obj.cached_absolute == _mo.CacheStatus.UNKNOWN \ or obj.cached_multiclan == _mo.CacheStatus.UNKNOWN: # The 'absolute' state has not yet been cached. Determine whether obj is an absolute # multiclan. is_absolute_mclan = obj.get_ground_set().is_subset( get_absolute_ground_set()) if obj.cached_multiclan == _mo.CacheStatus.UNKNOWN: if is_absolute_mclan: # If it is an absolute multiclan, it is also a multiclan. obj.cache_multiclan(_mo.CacheStatus.IS) else: # If it is not an absolute multiclan, it may still be a multiclan. is_mclan = is_member(obj) if not is_mclan: # If it is neither an absolute multiclan nor a multiclan, exit. (That it is # not a multiclan has already been cached in is_member().) return False # At this point, cached_multiclan == IS. Cache whether this is an absolute multiclan. assert obj.cached_is_multiclan obj.cache_absolute(_mo.CacheStatus.from_bool(is_absolute_mclan)) # At this point, cached_multiclan == IS. Return whether it is an absolute multiclan. return obj.cached_is_absolute
def is_absolute_member(obj: _mo.MathObject) -> bool: """Return whether ``obj`` is a member of the :term:`absolute ground set` of this algebra. :return: ``True`` if ``obj`` is an :term:`absolute clan`, ``False`` if not. .. note:: This function may call :meth:`~.MathObject.get_ground_set` on ``obj``. The result of this operation is cached. """ if obj.cached_is_not_multiclan: # If known to not be a multiclan, it's also not an absolute multiclan. No further caching. return False # The `or` clause in this `if` statement is a safety thing. It should never hit. if obj.cached_absolute == _mo.CacheStatus.UNKNOWN \ or obj.cached_multiclan == _mo.CacheStatus.UNKNOWN: # The 'absolute' state has not yet been cached. Determine whether obj is an absolute # multiclan. is_absolute_mclan = obj.get_ground_set().is_subset(get_absolute_ground_set()) if obj.cached_multiclan == _mo.CacheStatus.UNKNOWN: if is_absolute_mclan: # If it is an absolute multiclan, it is also a multiclan. obj.cache_multiclan(_mo.CacheStatus.IS) else: # If it is not an absolute multiclan, it may still be a multiclan. is_mclan = is_member(obj) if not is_mclan: # If it is neither an absolute multiclan nor a multiclan, exit. (That it is # not a multiclan has already been cached in is_member().) return False # At this point, cached_multiclan == IS. Cache whether this is an absolute multiclan. assert obj.cached_is_multiclan obj.cache_absolute(_mo.CacheStatus.from_bool(is_absolute_mclan)) # At this point, cached_multiclan == IS. Return whether it is an absolute multiclan. return obj.cached_is_absolute
def is_member(obj: _mo.MathObject) -> bool: """Return ``True`` if ``obj`` is a member of the :term:`ground set` of this :term:`algebra`. .. note:: This function calls :meth:`~.MathObject.get_ground_set` on ``obj``. """ _mo.raise_if_not_mathobject(obj) if not obj.cached_is_clan and not obj.cached_is_not_clan: obj.cache_is_clan(obj.get_ground_set().is_subset(get_ground_set())) return obj.cached_is_clan
def is_member(obj: _mo.MathObject) -> bool: """Return ``True`` if ``obj`` is a member of the :term:`ground set` of this :term:`algebra`. .. note:: This function may call :meth:`~.MathObject.get_ground_set` on ``obj``. The result of this operation is cached. """ _mo.raise_if_not_mathobject(obj) if not obj.cached_is_relation and not obj.cached_is_not_relation: obj.cache_is_relation(obj.get_ground_set().is_subset(get_ground_set())) return obj.cached_is_relation
def is_member(obj: _mo.MathObject) -> bool: """Return whether ``obj`` is a member of the :term:`ground set` of this :term:`algebra`. :return: ``True`` if ``obj`` is a :term:`multiclan`, ``False`` if not. .. note:: This function may call :meth:`~.MathObject.get_ground_set` on ``obj``. The result of this operation is cached. """ if obj.cached_multiclan == _mo.CacheStatus.UNKNOWN: is_multiclan = obj.get_ground_set().is_subset(get_ground_set()) obj.cache_multiclan(_mo.CacheStatus.from_bool(is_multiclan)) return obj.cached_is_multiclan
def is_absolute_member(obj: _mo.MathObject) -> bool: """Return whether ``obj`` is a member of the :term:`absolute ground set` of this algebra. :type obj: _mo.MathObject|_mo.Couplet :return: ``True`` if ``obj`` is an :term:`absolute couplet`, ``False`` if not. """ if not obj.is_couplet: # If known to not be a couplet, it's also not an absolute couplet. No further caching. return False # From this point on, `obj` is known to be a couplet. if obj.cached_absolute == _mo.CacheStatus.UNKNOWN: is_absolute_couplet = obj.left.is_atom and obj.right.is_atom obj.cache_absolute(_mo.CacheStatus.from_bool(is_absolute_couplet)) return obj.cached_is_absolute
def is_absolute_member(obj: _mo.MathObject) -> bool: """Return whether ``obj`` is a member of the :term:`absolute ground set` of this algebra. :type obj: _mo.MathObject|_mo.Couplet :return: ``True`` if ``obj`` is an :term:`absolute couplet`, ``False`` if not. """ if not obj.is_couplet: # If known to not be a couplet, it's also not an absolute couplet. No further caching. return False # From this point on, `obj` is known to be a couplet. if obj.cached_absolute == CacheStatus.UNKNOWN: is_absolute_couplet = obj.left.is_atom and obj.right.is_atom obj.cache_absolute(CacheStatus.from_bool(is_absolute_couplet)) return obj.cached_is_absolute
def _check_graph(obj: _mo.MathObject) -> bool: """Return ``True`` if ``obj`` is a :term:`graph`, ``False`` if not. ``obj`` is expected to be a :term:`clan`. """ return obj.is_set and obj.get_left_set() == _mo.Set('s', 'p', 'o') \ and _properties.is_regular(obj)
def is_absolute_member(obj: _mo.MathObject) -> bool: """Return ``True`` if ``obj`` is a member of the :term:`absolute ground set` of this algebra. :return: ``True`` if ``obj`` is an :term:`absolute relation`. .. note:: This function calls :meth:`~.MathObject.get_ground_set` on ``obj``.""" _mo.raise_if_not_mathobject(obj) return obj.get_ground_set().is_subset(get_absolute_ground_set())
def test_invalid_constructs(self): """Test invalid Atoms.""" self.assertRaises(TypeError, lambda: Atom(MathObject())) self.assertRaises(TypeError, lambda: Atom(Couplet(1, 2))) self.assertRaises(TypeError, lambda: Atom(Set())) self.assertRaises(TypeError, lambda: Atom(Undef())) self.assertRaises(TypeError, lambda: Atom([])) self.assertRaises(TypeError, lambda: Atom([7, '8'])) self.assertRaises(TypeError, lambda: Atom({})) self.assertRaises(TypeError, lambda: Atom({'one': 9, 2: 'ten'}))
def is_right_regular(mo: _mo.MathObject, _checked: bool = True) -> bool: r"""Return whether ``mo`` is :term:`right-regular` or `Undef()` if not applicable. Is implemented for :term:`clan`\s, :term:`multiclan`\s and :term:`set`\s of (sets of ...) clans. Is also defined (but not yet implemented) for any combination of sets or :term:`multiset`\s of clans. """ # pylint: disable=too-many-return-statements if _checked: if not isinstance(mo, _mo.MathObject): return _undef.make_or_raise_undef() # Check cache status. if mo.cached_right_regular == _mo.CacheStatus.IS: return True if mo.cached_right_regular == _mo.CacheStatus.IS_NOT: return False if mo.cached_right_regular == _mo.CacheStatus.N_A: return _undef.make_or_raise_undef(2) # Check type (right-regular is only defined on Sets and Multisets) and algebra memberships. if not mo.is_set and not mo.is_multiset: mo.cache_right_regular(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2) if _clans.is_member(mo): return _clans.is_right_regular(mo, _checked=False) if _multiclans.is_member(mo): return _multiclans.is_right_regular(mo, _checked=False) # Check higher (not yet defined) algebras. if mo.get_ground_set().get_powerset_level(_clans.get_ground_set()) > 0: mo_iter = iter(mo) elem1 = next(mo_iter) if not is_right_regular(elem1): mo.cache_right_regular(_mo.CacheStatus.IS_NOT) return False elem1_rights = elem1.get_rights() right_regular = all( is_right_regular(elem, _checked=False) and elem.get_rights() == elem1_rights for elem in mo_iter) mo.cache_right_regular(_mo.CacheStatus.from_bool(right_regular)) return mo.cached_is_right_regular # Nothing applied: 'right-regular' is not defined. mo.cache_right_regular(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2)
def is_right_regular(mo: _mo.MathObject, _checked: bool=True) -> bool: r"""Return whether ``mo`` is :term:`right-regular` or `Undef()` if not applicable. Is implemented for :term:`clan`\s, :term:`multiclan`\s and :term:`set`\s of (sets of ...) clans. Is also defined (but not yet implemented) for any combination of sets or :term:`multiset`\s of clans. """ # pylint: disable=too-many-return-statements if _checked: if not isinstance(mo, _mo.MathObject): return _undef.make_or_raise_undef() # Check cache status. if mo.cached_right_regular == _mo.CacheStatus.IS: return True if mo.cached_right_regular == _mo.CacheStatus.IS_NOT: return False if mo.cached_right_regular == _mo.CacheStatus.N_A: return _undef.make_or_raise_undef(2) # Check type (right-regular is only defined on Sets and Multisets) and algebra memberships. if not mo.is_set and not mo.is_multiset: mo.cache_right_regular(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2) if _clans.is_member(mo): return _clans.is_right_regular(mo, _checked=False) if _multiclans.is_member(mo): return _multiclans.is_right_regular(mo, _checked=False) # Check higher (not yet defined) algebras. if mo.get_ground_set().get_powerset_level(_clans.get_ground_set()) > 0: mo_iter = iter(mo) elem1 = next(mo_iter) if not is_right_regular(elem1): mo.cache_right_regular(_mo.CacheStatus.IS_NOT) return False elem1_rights = elem1.get_rights() right_regular = all( is_right_regular(elem, _checked=False) and elem.get_rights() == elem1_rights for elem in mo_iter) mo.cache_right_regular(_mo.CacheStatus.from_bool(right_regular)) return mo.cached_is_right_regular # Nothing applied: 'right-regular' is not defined. mo.cache_right_regular(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2)
def _is_powerset_property(mo: _mo.MathObject, ground_set, method) -> bool: """Return ``True`` if ``method`` returns ``True`` for all members of ``mo`` and ``mo`` is an element of an n-th power set of ``ground_set``. :param mo: The `MathObject` on which to operate. Must be a :term:`set`. :param ground_set: The :term:`ground set` of which the set ``mo`` should be part of (at the n-th :term:`power set` level). :param method: A property function (must return ``True``, ``False`` or `Undef()`) that should be run on all elements of ``mo``. It must be a function in this module. :return: ``True`` if this instance is element of an n-th power set of ``ground_set`` and all set elements return ``True`` for ``method``, ``False`` if it is an element of an n-th power set but any element returned ``False`` for ``method``, or `Undef()` if it isn't an element of an n-th power set. """ if mo.get_ground_set().get_powerset_level(ground_set) > 0: for element in mo: result = method(element) if result is _undef.Undef() or not result: return result return True return _undef.Undef()
def is_reflexive(mo: _mo.MathObject, _checked: bool = True) -> bool: r"""Return whether ``mo`` is :term:`reflexive` or `Undef()` if not applicable. Is implemented for :term:`couplet`\s, :term:`relation`\s, :term:`clan`\s, :term:`multiclan`\s and :term:`set`\s of (sets of ...) clans. Is also defined (but not yet implemented) for any combination of sets or :term:`multiset`\s of relations. """ # pylint: disable=too-many-return-statements if _checked: if not isinstance(mo, _mo.MathObject): return _undef.make_or_raise_undef() # Check cache status. if mo.cached_reflexive == _mo.CacheStatus.IS: return True if mo.cached_reflexive == _mo.CacheStatus.IS_NOT: return False if mo.cached_reflexive == _mo.CacheStatus.N_A: return _undef.make_or_raise_undef(2) # Check types and algebra memberships. if _couplets.is_member(mo): return _couplets.is_reflexive(mo, _checked=False) if not mo.is_set and not mo.is_multiset: mo.cache_reflexive(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2) if _relations.is_member(mo): return _relations.is_reflexive(mo, _checked=False) if _clans.is_member(mo): return _clans.is_reflexive(mo, _checked=False) if _multiclans.is_member(mo): return _multiclans.is_reflexive(mo, _checked=False) # Check higher (not yet defined) algebras. reflexive = _is_powerset_property(mo, _clans.get_ground_set(), is_reflexive) if reflexive is not _undef.Undef(): mo.cache_reflexive(_mo.CacheStatus.from_bool(reflexive)) return reflexive # Nothing applied: 'reflexive' is not defined. mo.cache_reflexive(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2)
def is_reflexive(mo: _mo.MathObject, _checked: bool=True) -> bool: r"""Return whether ``mo`` is :term:`reflexive` or `Undef()` if not applicable. Is implemented for :term:`couplet`\s, :term:`relation`\s, :term:`clan`\s, :term:`multiclan`\s and :term:`set`\s of (sets of ...) clans. Is also defined (but not yet implemented) for any combination of sets or :term:`multiset`\s of relations. """ # pylint: disable=too-many-return-statements if _checked: if not isinstance(mo, _mo.MathObject): return _undef.make_or_raise_undef() # Check cache status. if mo.cached_reflexive == _mo.CacheStatus.IS: return True if mo.cached_reflexive == _mo.CacheStatus.IS_NOT: return False if mo.cached_reflexive == _mo.CacheStatus.N_A: return _undef.make_or_raise_undef(2) # Check types and algebra memberships. if _couplets.is_member(mo): return _couplets.is_reflexive(mo, _checked=False) if not mo.is_set and not mo.is_multiset: mo.cache_reflexive(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2) if _relations.is_member(mo): return _relations.is_reflexive(mo, _checked=False) if _clans.is_member(mo): return _clans.is_reflexive(mo, _checked=False) if _multiclans.is_member(mo): return _multiclans.is_reflexive(mo, _checked=False) # Check higher (not yet defined) algebras. reflexive = _is_powerset_property(mo, _clans.get_ground_set(), is_reflexive) if reflexive is not _undef.Undef(): mo.cache_reflexive(_mo.CacheStatus.from_bool(reflexive)) return reflexive # Nothing applied: 'reflexive' is not defined. mo.cache_reflexive(_mo.CacheStatus.N_A) return _undef.make_or_raise_undef(2)
def _check_triple(obj: _mo.MathObject) -> bool: """Return ``True`` if ``obj`` is (almost) a :term:`triple`. Perform all checks except for the membership in the :term:`algebra of relations`.""" # noinspection PyUnresolvedReferences return isinstance(obj, _mo.Set) and obj.cardinality == 3 \ and obj.get_left_set() == _mo.Set('s', 'p', 'o')
def _check_graph(obj: _mo.MathObject) -> bool: """Return ``True`` if ``obj`` is (almost) a :term:`graph`. Perform all checks except for the membership in the :term:`algebra of clans`.""" return isinstance(obj, _mo.Set) and obj.get_left_set() == _mo.Set('s', 'p', 'o') \ and obj.is_left_regular()
def test_MathObject(self): """Create a MathObject.""" # MathObject itself can't be instantiated (it is an abstract base class). self.assertRaises(TypeError, lambda: MathObject()) self.assertRaises(TypeError, lambda: raise_if_not_mathobjects(1)) self.assertRaises(TypeError, lambda: raise_if_not_mathobjects(*[1]))